2017年9月28日木曜日

readline を使うアプリケーションでの入力を便利にする .inputrc

Linux で使われる主要なアプリケーションは,標準入力から入力を受け取るプロンプトを readline で実装していることが多い。最も有名なのは bash だろう。
実は,Ruby や Python で素朴に標準入力を受け取るプログラムを書いたときも,rlwrap コマンドを噛ましてやると,readline を使うようになる。

bash で vi モードや emacs モードの行内編集を有効化する人は多いのではないかと思うが,実はこれも readline の機能である。
つまり,これらの機能を設定するにあたり,bashrc を編集するより inputrc を編集するほうが,bash のみならず他のアプリケーションでも便利な入力機能が享受できる,というわけだ。そこで以下に私の設定を晒してみる。

set editing-mode vi
$if mode=vi
        set keymap vi-command
        Control-l: clear-screen

        set keymap vi-insert
        Control-l: clear-screen
$endif

"\C-p": history-search-backward
"\C-n": history-search-forward
TAB: complete
この設定は次の通りの機能をもつ
  • 行内編集で vi モードが使えるのでプロンプト上でやおら ESC すると hjkl で移動したり  x で削除できたりする
  • vi モードを有効化してても <C-L> でスクリーンクリアを有効化されるようにした
  • <C-P>,<C-N> で入力履歴から前方一致検索する
  • TAB での補完が効くようにした
設定ファイルのオプションの意味の説明は割愛(見ればわかるので)

2017年9月27日水曜日

Kubernetes 上の heapster に curl でダイレクトアクセス

まず前提として, https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/ に従い,kubernetes を bare metal サーバに kubeadm でインストールしたものとする。 今回は,CNI に Project Calico を使用した。

Kubernets v1.6.1
Calico v2.1.4

作業をはじめる前に,このバージョンで kubeadm を使い導入していると,クレデンシャルが自動生成されて,それを使わなければ kubectl での API アクセスが弾かれる
# cp /etc/kubernetes/admin.conf $HOME/admin.conf
$ export KUBECONFIG="$HOME/admin.conf"
また,curl でのアクセスも同様に弾かれるため,kube-proxy を利用する。
$ kubectl proxy --port=8080 &
ポートはお好きなように。この記事では 8080 で進めていく。

それではまず,heapster を導入する。
$ git clone https://github.com/kubernetes/heapster
$ kubectl create -f heapster/deploy/kube-config/influxdb
$ kubectl create -f heapster/deploy/kube-config/rbac/heapster-rbac.yaml
ちなみにこの記事を書いたときの heapster の最新の stable は v1.4.2 だが, git checkout v1.4.2 をしてこれを行ったとき,grafana の pod が無限再起動に陥ってしまいしばらく気がつかずに苦しんだ。
くそぅ……罠だ……k8s なんて嫌いです……ぐすん。
それはともかく,気分を切り替えて張り切って API アクセスしようと思う。
$ curl http://127.0.0.1:8080
{
  "paths": [
    "/api",
    "/api/v1",
    "/apis",
    "/apis/apps",
    "/apis/apps/v1beta1",
    "/apis/authentication.k8s.io",
    "/apis/authentication.k8s.io/v1",
    "/apis/authentication.k8s.io/v1beta1",
    "/apis/authorization.k8s.io",
    "/apis/authorization.k8s.io/v1",
    "/apis/authorization.k8s.io/v1beta1",
    "/apis/autoscaling",
    "/apis/autoscaling/v1",
    "/apis/autoscaling/v2alpha1",
    "/apis/batch",
    "/apis/batch/v1",
    "/apis/batch/v2alpha1",
    "/apis/certificates.k8s.io",
    "/apis/certificates.k8s.io/v1beta1",
    "/apis/extensions",
    "/apis/extensions/v1beta1",
    "/apis/policy",
    "/apis/policy/v1beta1",
    "/apis/rbac.authorization.k8s.io",
    "/apis/rbac.authorization.k8s.io/v1alpha1",
    "/apis/rbac.authorization.k8s.io/v1beta1",
    "/apis/settings.k8s.io",
    "/apis/settings.k8s.io/v1alpha1",
    "/apis/storage.k8s.io",
    "/apis/storage.k8s.io/v1",
    "/apis/storage.k8s.io/v1beta1",
    "/healthz",
    "/healthz/ping",
    "/healthz/poststarthook/bootstrap-controller",
    "/healthz/poststarthook/ca-registration",
    "/healthz/poststarthook/extensions/third-party-resources",
    "/healthz/poststarthook/rbac/bootstrap-roles",
    "/logs",
    "/metrics",
    "/swaggerapi/",
    "/ui/",
    "/version"
  ]
}
まず,kubernertes 自体の API について,ちゃんと kube-proxy が仕事して curl で API 一覧が見えることがわかる。

ここで,確認してみると良いのだが,/api/v1/namespaces をみるとわかるように,calico や heapser,kube-dns といった kubernetes のシステムの関連する Pod は kube-system という名前空間に存在する。
これは,kubectl get namespace でも確認可能。

そして,/api/v1/services を見にいくと,heapster というサービスが起動しており,これは,/api/v1/namespaces/kube-system/services/heapster に selfLink されている。
これもまた kubectl -n kube-system get svc と名前空間を指定して kubectl でサービス一覧を取得すれば同様のことがわかる。

さて,今回アクセスしたいのは heapster そのものの API なので,ここで,kube-apiserver の proxy を使う。
$ curl http://127.0.0.1:8080/api/v1/proxy/namespaces/kube-system/services/heapster/api/v1/model/namespaces/
[
  "default",
  "kube-system"
]
Kuernetes の API のルートに proxy というディレクトリが追加されているのがわかる。その下にサービスを指定して,その下に heapster 自体の REST API のエンドポイントを書くとこのように結果が得られる。
$ curl http://127.0.0.1:8080/api/v1/proxy/namespaces/kube-system/services/heapster/api/v1/model/namespaces/kube-system/pods/
[
  "kube-proxy-xw0k2",
  "calico-policy-controller-1777954159-3zcdp",
  "monitoring-influxdb-3871661022-g6dzx",
  "monitoring-grafana-973508798-98hcz",
  "kube-scheduler-cluster00",
  "kube-controller-manager-cluster00",
  "heapster-1528902802-mln1m",
  "calico-node-fxq75",
  "calico-node-bc4tk",
  "kube-proxy-9tnmn",
  "etcd-cluster00",
  "kube-dns-3913472980-093xh",
  "kube-apiserver-cluster00",
  "kube-proxy-lbgb2",
  "calico-etcd-3d4bf",
  "calico-node-r3rvh"
]
pod の一覧も取得できるし,
curl http://127.0.0.1:8080/api/v1/proxy/namespaces/kube-system/services/heapster/api/v1/model/namespaces/kube-system/pods/etcd-cluster00/metrics/uptime
{
  "metrics": [
  {
    "timestamp": "2017-09-27T07:09:00Z",
    "value": 13986309
  },
  {
    "timestamp": "2017-09-27T07:10:00Z",
    "value": 14046297
  },
  {
    "timestamp": "2017-09-27T07:11:00Z",
    "value": 14106296
  }
  ],
  "latestTimestamp": "2017-09-27T07:11:00Z"
}
特定の Pod について,メトリクスを取得することも自由自在,というわけだ。
なおここで得られるメトリクスの一覧は次からわかる。リンクは最新のタグの v1.5.0-beta.0 のもの。
https://github.com/kubernetes/heapster/blob/v1.5.0-beta.0/docs/storage-schema.md
このリンク先の表を以下に引用しておく。
Metric Name Description
cpu/limit CPU hard limit in millicores.
cpu/node_capacity Cpu capacity of a node.
cpu/node_allocatable Cpu allocatable of a node.
cpu/node_reservation Share of cpu that is reserved on the node allocatable.
cpu/node_utilization CPU utilization as a share of node allocatable.
cpu/request CPU request (the guaranteed amount of resources) in millicores.
cpu/usage Cumulative CPU usage on all cores.
cpu/usage_rate CPU usage on all cores in millicores.
filesystem/usage Total number of bytes consumed on a filesystem.
filesystem/limit The total size of filesystem in bytes.
filesystem/available The number of available bytes remaining in a the filesystem
filesystem/inodes The number of available inodes in a the filesystem
filesystem/inodes_free The number of free inodes remaining in a the filesystem
memory/limit Memory hard limit in bytes.
memory/major_page_faults Number of major page faults.
memory/major_page_faults_rate Number of major page faults per second.
memory/node_capacity Memory capacity of a node.
memory/node_allocatable Memory allocatable of a node.
memory/node_reservation Share of memory that is reserved on the node allocatable.
memory/node_utilization Memory utilization as a share of memory allocatable.
memory/page_faults Number of page faults.
memory/page_faults_rate Number of page faults per second.
memory/request Memory request (the guaranteed amount of resources) in bytes.
memory/usage Total memory usage.
memory/cache Cache memory usage.
memory/rss RSS memory usage.
memory/working_set Total working set usage. Working set is the memory being used and not easily dropped by the kernel.
network/rx Cumulative number of bytes received over the network.
network/rx_errors Cumulative number of errors while receiving over the network.
network/rx_errors_rate Number of errors while receiving over the network per second.
network/rx_rate Number of bytes received over the network per second.
network/tx Cumulative number of bytes sent over the network
network/tx_errors Cumulative number of errors while sending over the network
network/tx_errors_rate Number of errors while sending over the network
network/tx_rate Number of bytes sent over the network per second.
uptime Number of milliseconds since the container was started.
すべてのカスタムのメトリクスは custom/ に置かれるそうな。

P. S.
各サービスの API のエンドポイント,kubectl cluster-info みたら普通に書いてあるやんけ……。

macOS で Mach-O バイナリにリンクされてる動的リンクのライブラリを調べる

普段 CLI を使う環境が Linux/*BSD なもんでつい手癖で ldd を使ってしまったが,ldd は glibc の付属ツールである。macOS の場合,
otool -L a.out
とかすれば良いらしい。他にも Mach-O のオブジェクトファイルの情報を出せる ObjectDump とか dyld の情報出せる dyldinfo とか知らないコマンドがいっぱいあるっぽいので難しい。

gcc のバージョン番号の大小をシェルスクリプトで判別するやつ

$ gcc -dumpversion | awk -F. '{printf "%2d%02d%02d", $1,$2,$3}'
70200
これで整数になるのであとは test -gt とか test -ne とか使う

P. S.
最初
$ gcc -v 2>&1 | tail -n 1 | awk '{print $3}'
とかやってバージョン番号をダンプしてたがもっと便利なオプションがあってよかった。

2017年9月21日木曜日

最近 Vivaldi とか Slack が Linux と GNOME でよく刺さる [一応解決?]

先一昨日にカーネルアップデートをして ArchLinux のカーネルが 4.13.2-1-zen になった。
一昨日と昨日はあんまり触ってなくて,今日触ってたら,Vivaldi とか Slack でよく刺さるようになってしまった。
メモリ不足で Wayland のセッションが OOM かなんかに回収されて再起動するときの挙動に似てたので最初は気にしなかったのだが,
なんか復活したセッションがまたクラッシュした上にリカバリできなくなって X に fallback するようになった。

これはマズい挙動なのでは?
とりあえず journalctl をみてみる。

盛大に壊れてる。

で,エラーメッセージで調べたところ(調べようとして Vivaldi を起動してまた刺してしまって,最終的に reboot してから Windows で調べた),
89360 – [bdw-u iommu] DMAR error -> GPU hang https://bugs.freedesktop.org/show_bug.cgi?id=89360
はい,バグですね。
そういえば使ってるマシンは VAIO Pro 13 | mk2 の,Core i5 モデルなので,Broadwell であり,GPU は Intel HD Graphics 5500 だ。
ビンゴである。

Slack のほうも /usr/share/applications/slack.desktop の起動コマンドから --disable-gpu フラグを外してたりしました。はい……。

とりあえず Bugzilla にあった通り,ブートローダーのカーネルコマンドラインに,
intel_iommu=igfx_off
を追加してみたところ,今のところまだ刺さらずにこのブログ記事が Vivaldi で書けている。

2017年9月17日日曜日

BibLaTeX で参考文献の表示をカスタマイズする

 最近原稿の参考文献は pBibTeX ではなく Biber+BibLaTeX を使うようになりました。
BibLaTeX はスタイルファイルを書き換えなくとも表示がカスタマイズできるところが美点です。そこで最近やったカスタマイズについてメモを残します。

前提として,ACM のスタイルファイルで \bibliographystyle{abbrvnat} を使ったときに表示を近づけようとしています。そこで,パッケージの設定は次の通り。
\usepackage[backend=biber,style=trad-abbrv,natbib=true]{biblatex}

doi や URL を表示しない

私は Mendeley を文献管理に使っており,なるべく得られた情報はすべてデータベース化しておきたいという考えの持ち主でもあるので,doi や PDF の URL も記録しているのですが,その全てを原稿中で表示したいわけではないため,次のようにしました。

会議名の先頭に In Proc. of を付けたい

会議名は会議名として記録・分類したいので,会議名の頭に In Proc. of とか In Proceedings of を付けて周るようなマネはしたくありません。とはいえ,それは Mendeley での管理の話で,原稿の中では会議の名前にだけ In Proc. of というのを付けたいです。しかし,このスタイルのデフォルトだと会議でも論文誌でも In Booktitle となるようなので,今回は \renewbibmacro{} を使い in: という bibmacro を変更します。

会議名と会議の略称の体裁

最後に,これは私固有の問題ですが,Mendeley で会議名を Proc.Title,略称を Series に入れて管理していると,BibTeX ファイルにはそれぞれが booktitle と series に入れられます。これは,
Book Title, Series,
と表示されますが,これを
Book Title (Series),
にしたいので,$TEXMF/tex/biblatex/biblatex-trad/trad-standard.bbx にある定義を参照しました。これによると,inproceedings の時の会議名の表示は series+number:emphcond という bibmacro で定義されていたので,エントリのタイプが inproceedings の時だけ表示を変え,そうでないときは元の定義をそのまま使うようにしました。

以上より,次のような結果を得られます。

元の表示

あふたー

2017年9月7日木曜日

QEMU のイメージファイルの特定のパーティションをホストにマウントする

こういうときだいたいみなさんlosetupコマンドで loopback device にして mount すると思います。raw ディスクだとそれでも良かったりしますが,qcow2 の 3 番目のパーティションをマウント,とかやろうとすると少し厄介。

これは次のようにして解決できます。
# modprobe nbd
# qemu-nbd --connect=/dev/nbd0 ./target.qcow2
まずこれで /dev/nbd0 がブロックデバイスとして使えるようになります。ここで,
# fdisk -l /dev/nbd0
Disk /dev/nbd0: 8 GiB, 8589934592 bytes, 16777216 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x97d8dd27

Device Boot Start End Sectors Size Id Type
/dev/nbd0p1 * 2048 206847 204800 100M 83 Linux
/dev/nbd0p2 206848 1202175 995328 486M 82 Linux swap / Solaris
/dev/nbd0p3 1202176 16777215 15575040 7.4G 83 Linux
これで 3 番目のパーティションは 1202176 セクタ目から開始していて,セクタサイズが 512 bytes であることが読み取れるので,3 番目のパーティションは 1202176 * 512 = 615514112 byte 目から始まることがわかります。
従って,
# mount -o offset=615514112 /dev/nbd0 /mnt
これでマウントができます。
ここまで書いて気がついたがfdiskを実行してから offset を指定するまではシェルスクリプトで自動化できそうですね。
例えば 3 番目のパーティションの offset byte を知りたい場合,
expr \
$(fdisk -l /dev/nbd0 | grep -A 10 'Device\s*Boot' \
    | sed -n '3p' | awk '{print $2}') \
\* \
$(fdisk -l /dev/nbd0 | grep 'Sector size'
    | cut -d' ' -f 4)
これで求まりますね。


ちなみに,/dev/nbd0 からイメージを取り外す時は,
# qemu-nbd --disconnect=/dev/nbd0