Raspberry Pi OSでdmesg
のオレオレ版的なモノが欲しくなって探したら、期待したものを見つけたので紹介します。
何かしらのdaemonを作って走らせる際に、「ログを吐いておきたいけどjournald
に貯めておくほどではなく、気になるときに最新のを少し見れればいい」というぐらいの温度感で標準出力を見たいときに便利です。syslog
にゲロゲロ吐かれてるけどそんなにいらんねん、とかいう時にも使えそう。
emlog -- the EMbedded-system LOG-device
開発は2018年で止まっていますが、2021年1月時点でのRasperry Pi OS 5.4.72+でビルド1して普通に動きました。
dmesg
っぽく動くリングバッファを任意の名前で作ることが出来、このリングバッファは名前付きパイプと違い非同期で読み込みと書き込みを行えます。
ビルド方法
カーネルモジュールのビルドについては、Raspberry Pi でカーネルモジュールビルドの準備を参照しました。
書いてあるとおりに準備し、githubをcloneしてmake
するだけ。わたしの環境ではKDIR
で参照する/lib/modules/5.4.72+/build
のsymlinkがなんか辿れなかった2ので、make
時にKDIR
を別途指定しましたが、それぐらい。
インストール
ビルドして出来たemlog.ko
を適当な場所においてmodprobe
で入れたり/etc/modules
に追記して再起動すると、/dev/emlog
が生えます。
同時にログバッファを作るコマンドmkemlog
が出来ているので、/usr/local/sbin
とかに入れましょう。
mkemlogのつかいかた
$ mkemlog
mkemlog: usage: mkemlog [size_in_kilobytes] [mode] [uid]
引数には「ログバッファのファイルパス」「バッファサイズ」「ファイルモード」「ファイルオーナUID」を取ることが出来ます。このコマンドは内部でmknod
を呼ぶのでroot
で起動しないとコケます。
ファイルモードはデフォルトだと660
3のようです。
systemdで管理する
Raspberry Pi OSはsystemdでdaemonを管理しているので、それに乗ります。
なお最近はStandardOutput
にfile:/foo/bar
とか書けます4が、mkemlog
が走る前に普通のファイルを生成するので衝突します。ExecStart
で起動する際にsh
経由で起動しリダイレクトさせる古の手法を使います。
[Service]
StandardOutput = null
StandardError = journal
rootで起動し、終了時にログバッファを消す
[Service]
ExecStartPre = mkemlog /tmp/hoge.log 4 0644
ExecStart = /bin/sh -c 'exec /usr/local/sbin/hoge > /tmp/hoge.log'
ExecStopPost = rm /tmp/hoge.log
特段コメントすることのない、普通のService
セクションです。
rootで起動し、終了時にログバッファを消さない
[Service]
ExecStartPre = -mkemlog /tmp/hoge.log 4 0644
ExecStart = /bin/sh -c 'exec /usr/local/sbin/hoge > /tmp/hoge.log'
ログバッファを消していないので、restart
した場合にmkemlog
がFile exists
で失敗します。そこでExecStartPre
で実行するコマンドにプレフィクス-
をつけて、実行結果によらず成功判定5させます。
nobodyで起動、終了時にログバッファを消す
[Service]
User = nobody
ExecStartPre = +mkemlog /tmp/hoge.log 4 0644 65534
ExecStart = /bin/sh -c 'exec /usr/local/sbin/hoge > /tmp/hoge.log'
ExecStopPost = rm /tmp/hoge.log
ExecStartPre
で実行するコマンドにプレフィクス+
をつけるとrootでコマンドを起動5します。
nobodyで起動、終了時にログバッファを消さない
[Service]
User = nobody
ExecStartPre = -+mkemlog /tmp/hoge.log 4 0644 65534
ExecStart = /bin/sh -c 'exec /usr/local/sbin/hoge > /tmp/hoge.log'
ExecStartPre
でプレフィクスを2つつける、合せ技。
バッファリングについて
mkemlog
で生成するログバッファは書き込まれたものをすぐに読むことが出来ますが、書き込む側がバッファリングしているとそれに準じるので注意が必要です。
例えばPerlの場合STDOUTをターミナル以外へリダイレクトするとブロックバッファリングになります6。
バッファリングはPerlだと$|
で制御できますし、プログラム実装をいじらない場合はstdbufやunbufferのようなツール7を使うことになります。
-
ビルドしたマシンはRaspberry Pi Zero W。こんな小さなやつでもビルドできちゃうのすごい。 ↩
-
なにかあるんでしょうけど、理由を調べてない。。。 ↩
-
詳細はsystemd.execを参照。 ↩
-
詳細はsystemd.serviceを参照。 ↩ ↩2
-
perlvar - Perl で定義済みの変数 (英語版) の「
$|
」を参照。 ↩ -
ちなみにPerlで試した場合、unbufferは効果があったけどstdbufは効果がありませんでした。 ↩