昨年末に Go言語で書いた Web アプリケーションの習作をサービス化して公開するところまでやってみた - えいのうにっき で公開したサービス・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-systemd や systemdからFluentdにデータを流し込む - Qiita といった記事も見つかったり、もしくは syslog で /var/log/messages に......って感じだろうと思うのだけど、悪いことに今回出力してるのはLTSV、構造化ログだ。Journal や syslog で出力されたログからLTSV部分だけ取り出して......、、とか、いかにも考えたくない。
じゃあ systemd にも supervisor でいうところの stdout_logfile
相当のディレクティブがあるのか、と思いきや、ちょっとググったかんじだとさっぱり見つからない。かといって、systemd で ExecStart=/path/to/program > outputfile
などと指定するのはなんだか気持ち悪い、絶対なにか違う方法があるはず......と、移行そのものではなく「ログ出力をどうするか」というところでデーモン化手段の切り替えが阻まれてしまっていた。
そんな折、このことを社内のLT大会で話してみたところ、以下のような状況のようだ、との知見が得られた。
- systemd で動くプログラムの標準出力の取り扱いについては、Support pointing StandardInput/StandardOutput/StandardError to file · Issue #3991 · systemd/systemd · GitHub でも議論されている
- 去年(2017年)の11月に
StandardOutput
ディレクティブのサポートが追加された! ExecStart=/bin/sh -c 'exec /path/to/program > /path/to/log 2&>1'
と書くのが今のところの定番っぽい
ということで、StandardOutput
が実際に使えるようになるのはまだもう少し先だとは思うけど、ExecStart
でダイレクトにファイルに出力させることは現時点でのセオリーであることが晴れて判明し、個人的にはすっきりした気持ちで、冒頭の変更を加えましたとさ。という話。
(今後 StandardOutput
を指定したときって、ファイルにも出力しつつ Journal にも出力される......のかなぁ?)
【オマケ】systemd・自分用メモ
Service
type
simple
としておくことで、起動したタイミングで起動完了とみなしてくれる(デフォルト)forking
type もある
Install
WantedBy