如何殺死 Linux 中的殭屍進程
據傳說,魂去身存還能活動的肉體名叫殭屍,常常出沒於深山老林之中。然而在現代,伴隨著 C 語言和 Unix 系統的誕生,賽博殭屍開始活躍於每一台電腦中。或者說,在使用電腦的過程中,有那麼一些進程由於種種原因,變成了雖然已經被自我殺死但還仍然佔用著資源的殭屍進程。與此相對的還有已經失去父進程、無法被正常調用本應該死亡但還在運行的孤兒進程。關閉孤兒進程是比較簡單的一件事,但檢索和 kill 殭屍進程要困難許多。
如何理解進程
程序們被執行的時候,它們會叫出一系列進程作為小弟,去具體跑腿來實現功能。比如我們可以用 ps 命令來查看當前的所有進程。
當然,不僅是程序會創建新進程,進程也可以創建新進程,這種情況下就會產生類似樹形的結構,我們可以用 pstree 來查看進程樹的情況。
更大的進程樹會像這樣:
可以看到每個進程都在系統中有一個編號,即 pid。pid 1的進程就是系統引導中執行的第一個進程,也就是 init 進程。在新版本的 Linux 中通常叫做 systemd。
使用 kill 來殺死進程
kill 命令是 Linux 系統中的一把最鋒利的劍,你可以用它來終止 Linux 系統中所有指定的進程。而只刪除一個進程會比較危險,要小心它的家人依舊存活在你的系統中,通過佔用資源來報復你。可以嘗試 killall 指令,它會幫助你下「誅九族」的命令。
如果單獨殺掉父進程而子進程沒能自動結束,子進程就變成了孤兒進程,但只要通過 ps 命令搜索到它的 pid,依舊可以簡單的結束掉它們。
如何殺死殭屍進程
那麼殭屍進程又有什麼特殊的呢?因為它們已經死過一次了,所以不能再殺掉了。
如果一個子進程自然終止,它們都會變成臨時的殭屍進程,直到父進程通過代碼釋放掉它們本來所佔用的資源。但如果父進程這一步失敗或被忽略了,這個子進程就變成了真正的殭屍進程,雖然不在運行,但還是空占著資源。所以你普通地用 kill 命令來結束掉它們的時候,一般情況下是不起作用的。
那麼要怎麼殺掉它們呢?答案是結束掉它們的父進程。首先用 ps 指令來找到需要殺死的殭屍進程,然後用 pstree 指令尋找它們的父進程,結束掉父進程,就可以實現目標了。假設 pid 827 是我們要結束的殭屍進程,而 pid 749是它的父進程,我們可以
$ sudo kill -9 749
來結束掉它們的生命。
結束掉父進程是一個很方便的做法,但要注意最極端的情況:父進程的 pid 是 1。這種時候殺掉父進程,它會自動重啟,變成不死的殭屍 🙁
參考資料: