如何找到并殺掉 Linux 系統中的僵尸進程
這是一個關于如何尋找 Linux 系統僵尸進程并殺死它們的小知識。你也可以從中了解到關于進程和僵尸進程的一些知識。
在了解僵尸進程之前,讓我們來復習一下什么是 Linux 進程。
簡而言之,進程 是一個程序的運行實例。它可能運行在前端(比如有交互的進程),也可能運行在后端(比如無交互或自動運行的進程)。它可能是一個父進程(運行期間創建了其他進程),也可能是一個子進程(由其他進程所創建)。
在 Linux 系統中,除 PID 為 0 的第一個 init
進程(或 systemd
)外,其余進程都有父進程。進程也可以擁有自己的子進程。
不相信?可以試試在終端中使用 pstree
命令查看進程的樹型結構,你能看到系統各個進程的“家族樹”。
Linux系統里的僵尸進程是什么?
子進程死亡后,它的父進程會接收到通知去執行一些清理操作,如釋放內存之類。然而,若父進程并未察覺到子進程死亡,子進程就會進入到“僵尸”狀態。從父進程角度看,子進程仍然存在,即使子進程實際上已經死亡。這就是“僵尸進程”(也被稱為“已消失進程”)是如何產生并存在于系統中的。
這里有一個來自 Turnoff.us 的關于僵尸進程的非常有趣的看法:
Image credit: Turnoff.us
你真的需要關心僵尸進程嗎?
重點要說的是,僵尸進程并沒有像它的名稱那樣看起來可怕。
但如果系統的內存已經所剩不多或者有太多的僵尸進程在吃掉內存,問題會變得糟糕。同樣,大部分 Linux 系統進程最大 PID 設置為 32768,如果過多僵尸進程導致其他重要任務沒有 PID 可用,你的系統會發生崩潰。
這是真實可能發生的,它有一定的概率,特別當存在一個編碼糟糕的程序開始大量產生僵尸進程的時候。
在這種情況下,找到并殺死僵尸進程是一個明智的做法。
如何找到僵尸進程
Linux 系統中的進程可能處于如下狀態中的一種:
D
= 不可中斷的休眠I
= 空閑R
= 運行中S
= 休眠T
= 被調度信號終止t
= 被調試器終止Z
= 僵尸狀態
那如何查看進程和它的當前狀態呢?一個簡單的方法是在終端中使用 top 命令。
Top command show processes and their status
正如你在上面截圖中看到的,截圖中共有 250 個任務(進程),其中 1 個處在 “運行中” 狀態,248 個進程處于 “休眠” 狀態,還有一個處于 “僵尸” 狀態。
現在問題進入下一步,如何殺死 “僵尸” 進程?
如何找到并殺死一個僵尸進程?僵尸進程能被殺死嗎?
僵尸進程已經死了,要如何才能殺死一個已經死亡的進程呢?
在僵尸電影中,你可以射擊僵尸的頭部或燒掉它們,但在這里是行不通的。你可以一把火燒了系統來殺死僵尸進程,但這并不是一個可行的方案。
一些人建議發送 SIGCHLD
給父進程,但這個信號很可能會被忽略。還有一個方法是殺死父進程來殺死僵尸進程,這聽起來很野蠻,但它卻是唯一能確保殺死僵尸進程的方法。
首先,通過在終端中 使用 ps 命令 我們列舉僵尸進程,得到它們的進程 ID:
ps ux | awk '{if($8=="Z+") print}'
ps ux
命令輸出的第 8 列顯示了進程狀態。上述命令只會打印所有處在 Z+ 狀態(表示僵尸狀態)的進程。
確認了進程 ID 后,我們可以得到它的父進程 ID:
ps -o ppid= -p <child_id>
你也可以將上述兩個命令結合在一起,直接得到僵尸進程的 PID 及其父進程的 PID:
ps -A -ostat,pid,ppid | grep -e '[zZ]'
現在你得到了父進程 ID,使用命令行和得到的 ID 號 終于可以殺死進程了:
kill -9 <parent_process_ID>
Killing parent process
再次運行 ps
命令或 top
命令,你可以驗證僵尸進程是否已經被殺死。
恭喜!現在你知道怎么清理僵尸進程了。