Upstartを使っていると停止させた時にプロセスが死なないことがあることに気づいた。
それは特定の条件、たぶん2回以上プロセスがforkされると、孫プロセスが死なないというものだ。
※Linuxの正常な動作っぽいが。
たとえば、
start on runlevel [2345] stop on runlevel [!2345] respawn script su - vagrant -c '/bin/sh /usr/local/bin/hoge >> /var/log/app/hoge 2>&1' end script
とやった場合に起こる。
プロセスツリーをみると以下のようになっている。
root 14648 0.0 0.0 48484 1452 ? S 22:36 0:00 \_ su - vagrant -c /bin/sh /usr/local/bin/hoge >> /var/log/app/hoge.log 2>&1 vagrant 14649 0.0 0.1 108176 1636 ? Ss 22:36 0:00 \_ -bash -c /bin/sh /usr/local/bin/hoge >> /var/log/app/hoge.log 2>&1 vagrant 14718 0.0 0.0 106064 1308 ? S 22:36 0:00 \_ /bin/sh /usr/local/bin/hoge
で、いろいろ調べたが、
Upstartの expect daemon か expect fork を使えば回避出来そうなことが書かれていた。
しかしやってみたが解決しない…。
しょうがないので、いろいろ試した結果以下の様な書き方なら大丈夫だった。
start on runlevel [2345] stop on runlevel [!2345] respawn script su - vagrant -c '/bin/sh /usr/local/bin/hoge' 2>&1 | su - vagrant -c 'tee -a /var/log/app/hoge.log' end script
プロセスツリーをみると以下のようになっていた。
root 12550 0.0 0.0 48484 1452 ? S 22:32 0:00 \_ su - vagrant -c /bin/sh /usr/local/bin/hoge vagrant 12552 0.3 0.0 106064 1308 ? Ss 22:32 0:00 | \_ /bin/sh /usr/local/bin/hoge root 12551 0.0 0.0 48484 1456 ? S 22:32 0:00 \_ su - vagrant -c tee -a /var/log/app/hoge.log vagrant 12553 0.3 0.0 101020 732 ? Ss 22:32 0:00 \_ tee -a /var/log/app/hoge.log
これならそれぞれ一回しかforkしていないから大丈夫みたいだ。
また他のやり方としては、
http://stackoverflow.com/questions/12200217/can-upstart-expect-respawn-be-used-on-processes-that-fork-more-than-twice
にあるように、
pre-start scriptとpost-stop scriptを使って解決するやり方もある。
ugly hackなのであんまりやりたくないが…背に腹は代えられない。
ちなみに、
Upstartの代替として期待されているのが、Systemdだが、 http://ja.wikipedia.org/wiki/Systemd
Systemdは「PIDではなく cgroups を使ってサービスプロセス群を監視する。つまり、デーモンが2回forkしてもsystemdから逃れることはできない。」
とあるので、Systemdがきたら上記の問題は解決しそうだ。