
進程狀態轉換圖
kill和kill -9,兩個命令在linux中都有殺死進程的效果,然而兩命令的執行過程卻大有不同,在程序中如果用錯了,可能會造成莫名其妙的現象。
執行kill(不加 -* 默認kill -15)命令,系統會發送一個SIGTERM信號給對應的程序。當程序接收到該signal信號后,將會發生以下事情:
程序立刻停止
當程序釋放相應資源后再停止
程序可能仍然繼續運行
大部分程序接收到SIGTERM信號后,會先釋放自己的資源,然后再停止。但是也有程序可能接收信號后,做一些其他的事情(如果程序正在等待IO,可能就不會立馬做出響應,我在使用wkhtmltopdf轉pdf的項目中遇到這現象),也就是說,SIGTERM多半是會被阻塞的。
然而kill -9命令,系統給對應程序發送的信號是SIGKILL,即exit。exit信號不會被系統阻塞,所以kill -9能順利殺掉進程。
小結:在使用 kill -9 前,應該先使用 kill -15,給目標進程一個清理善后工作的機會。如果沒有,可能會留下一些不完整的文件或狀態,從而影響服務的再次啟動。
Perl語言專家Randal Schwartz在一篇短文里這樣寫:
no no no.不要使用kill -9.
它沒有給進程留下善后的機會:
1) 關閉socket鏈接
2) 清理臨時文件
3) 將自己將要被銷毀的消息通知給子進程
4) 重置自己的終止狀態
等等。
通常,應該發送15,等一兩秒鍾,如果沒效果,發送2,如果還不行,發送1。如果還不行,那你應該把那個程序刪掉,因為那個程序寫的太爛了!
不要使用kill -9。不要用收割機來修剪花盆里的花。
總之,在使用kill -9前,你應該先使用kill -15,給目標進程一個清理善后工作的機會。(進程也許無法捕捉或直接忽略SIGKILL信號,但它們可以,通常也是能夠捕捉SIGTERM信號的。)如果你不留機會讓進程完成清理工作,它們會留下一些不完整的文件或狀態,當系統重啟時,程序將無法理解這些狀態。
strace/truss,ltrace和gdb都是查看一個卡住的進程因何卡住的好工具。(Solaris里的truss -u非常好用;)Solaris里還有一些非常有用的/proc相關的工具,有一些已經被移植到了Linux上。