kill コマンドって、プロセスを終了させるものかと勘違いしていた
今までは、「kill すればプロセスは終了する」って思ってたので、例えば、以下のようなコマンドでデーモンプロセスが終了しないのを不思議に思ってた。
$ kill [デーモンのプロセス番号]
(いや、man 読んどけよって話なんですが・・・)
kill で終了させられない例
例として、rails のデフォルトのweb サーバであるwebrick
$ ruby script/server webrick -d $ ps ax | grep ruby 518 ?? S 0:00.00 ruby script/server webrick -d $ kill 518 $ ps ax | grep ruby 518 ?? S 0:00.00 ruby script/server webrick -d
kill したのに終了してねー(⊃д⊂)
今までやってた対処法
$ kill -KILL 518
これなら終了する。
この時思ってた疑問は、以下の2つ。
- kill -KILL って冗長じゃないか?
- kill -KILL ってプロセスを強制終了させるらしいけど、後始末されずに終了するので最終手段って聞いたことがあるぞ
kill はプロセスにシグナルを送るコマンド
man を読むと。
The kill utility sends a signal to the processes specified by the pid operand(s).
・・・プロセスを終了させるんじゃないのね。シグナルを送るコマンドなのね。で、シグナルの中に、プロセスを終了させる意味を持つシグナルがあるだけなのね。馬並みなのね。
kill って名前おかしいだろ!(これは、UNIX の歴史的な経緯があり、議論がつきないらしい)。
kill でwebrick が終了しない理由
kill がシグナルを送るってことは分かったけど、以下のように書くと終了するプロセスもある。
$ tail -f hoge.txt &
....
$ ps ax | grep tail
569 s002 SN 0:00.00 tail -f hoge.txt
$ kill 569
[1] + terminated tail -f hoge.txt
これは、kill がデフォルトのシグナルとして「15(TERM)」を送信するから。よく見ると、「terminated」って書いてある。
ってことは、webrick がkill で終了しないのは、「kill -TERM」で終了しないってこと。つまり、webrick はTERM のシグナルを無視するってことだ。じゃあ、何のシグナルなら終了するのかソースを読む。
61 trap("INT") { server.shutdown }
おぉ、ばっちり「INT」のシグナルで終了するって書いてある。そういえば、webrick を「-d」なしで起動してた時は「Ctrl-C」で終了させてた。これって、INT のシグナルを送ってるのと同じことじゃん。この辺り全然理解してなかった・・・。
結論言うと、デーモンのwebrick は次のようにすれば終了する。
$ kill -INT [webrick デーモンのプロセス番号]
lighttpd + fcgi で動かしているならこんな感じ。(pkill, pgrep 使ってないけど)
$ ps ax | grep fcgi | grep -v grep | awk '{print $1}' | xargs sudo kill -INT; sudo /etc/init.d/lighttpd restart