えいのうにっき

a-knowの日記です

systemd で動くプログラムの標準出力をファイルに出力させたい

昨年末に Go言語で書いた Web アプリケーションの習作をサービス化して公開するところまでやってみた - えいのうにっき https://blog.a-know.me/entry/2017/12/26/234528 で公開したサービス・Yukizuri のデーモン化手段を、今日、supervisor から systemd に変更した。理由は単純で、会社の同僚(先輩)と「なんで supervisor 使ったの?」「今なら systemd がいいんじゃない?」といったような会話があったため(別に咎められたわけではない)。

今まで supervisor で以下のような指定をして動かしていたものを、

; for yukizuri
[program:yukizuri]
command=/var/www/yukizuri/app/yukizuri.bin -addr=":8080" -logging=true
autostart = true
startsecs = 1
user = root
redirect_stderr = true
stdout_logfile = /var/www/yukizuri/log/production.log

systemd に切り替えるにあたり、以下のようにした。

[Unit]
Description=Yukizuri service

[Service]
Type=simple
ExecStart=/bin/sh -c 'exec /var/www/yukizuri/app/yukizuri.bin -addr=":8080" -logging=true > /var/www/yukizuri/log/production.log'
ExecStop=/bin/kill -SIGTERM $MAINPID
ExecReload=/bin/kill -SIGTERM $MAINPID && /bin/sh -c 'exec /var/www/yukizuri/app/yukizuri.bin -addr=":8080" -logging=true > /var/www/yukizuri/log/production.log'
Restart = always

[Install]
WantedBy = multi-user.target

と、結論だけみると「ふーん」という感じなのだけど、ここに至るまでに少し紆余曲折があった。

systemd で動くプログラムの標準出力をファイルに吐き出させたい

サービス公開時のブログでも書いているが、Yukizuri はLTSV形式のアプリケーションログを標準出力として吐く。supervisor を使う場合には stdout_logfile のおかげで、それを苦労せずにファイルに出力させられる。Yukizuri では、このファイルを fluentd の in_tail プラグインで舐めて、BigQuery に送っている。

systemd の場合、何もしなければログは Journal に出力される。つまりバイナリ。fluent-plugin-systemdsystemdからFluentdにデータを流し込む - Qiita といった記事も見つかったり、もしくは syslog で /var/log/messages に......って感じだろうと思うのだけど、悪いことに今回出力してるのはLTSV、構造化ログだ。Journal や syslog で出力されたログからLTSV部分だけ取り出して......、、とか、いかにも考えたくない。

じゃあ systemd にも supervisor でいうところの stdout_logfile 相当のディレクティブがあるのか、と思いきや、ちょっとググったかんじだとさっぱり見つからない。かといって、systemd で ExecStart=/path/to/program > outputfile などと指定するのはなんだか気持ち悪い、絶対なにか違う方法があるはず......と、移行そのものではなく「ログ出力をどうするか」というところでデーモン化手段の切り替えが阻まれてしまっていた。

そんな折、このことを社内のLT大会で話してみたところ、以下のような状況のようだ、との知見が得られた。

ということで、StandardOutput が実際に使えるようになるのはまだもう少し先だとは思うけど、ExecStart でダイレクトにファイルに出力させることは現時点でのセオリーであることが晴れて判明し、個人的にはすっきりした気持ちで、冒頭の変更を加えましたとさ。という話。

(今後 StandardOutput を指定したときって、ファイルにも出力しつつ Journal にも出力される......のかなぁ?)

【オマケ】systemd・自分用メモ