0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Raspberry Pi OSでプログラム独自のリングバッファロギング

Posted at

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で起動しないとコケます。

ファイルモードはデフォルトだと6603のようです。

systemdで管理する

Raspberry Pi OSはsystemdでdaemonを管理しているので、それに乗ります。

なお最近はStandardOutputfile:/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した場合にmkemlogFile 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だと$|で制御できますし、プログラム実装をいじらない場合はstdbufunbufferのようなツール7を使うことになります。

  1. ビルドしたマシンはRaspberry Pi Zero W。こんな小さなやつでもビルドできちゃうのすごい。

  2. githubのmkemlog.cを参照。

  3. 詳細はsystemd.execを参照。

  4. 詳細はsystemd.serviceを参照。 2

  5. perlvar - Perl で定義済みの変数 (英語版) の「$|」を参照。

  6. ちなみにPerlで試した場合、unbufferは効果があったけどstdbufは効果がありませんでした。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?