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