Linux 中的殭屍進程:尋找、移除、預防
15 分鐘閱讀 - 2026年5月19日

學習如何在 Linux 中識別、移除和預防殭屍進程。伺服器管理員的指令、程式碼修正和監控技巧。
Linux 中的殭屍程序:如何查找與移除
殭屍程序是指已執行完畢但仍佔用核心程序表中一個槽位的子程序。其存在的原因在於父程序尚未呼叫 wait() 來獲取其退出狀態。殭屍進程不會消耗 CPU 或記憶體,但每個進程都佔用一個 PID。若累積過多,系統將無法生成新進程。本文將介紹如何識別、移除這些進程,以及從源頭防止它們出現。
為何伺服器上的殭屍進程至關重要
單一的殭屍進程並無害處。問題在於它們累積時才會產生。Linux 的 PID 空間是有限的:32 位元系統為 32,768,64 位元系統則最多可達 4,194,304。若殭屍進程填滿進程表,核心便無法建立新進程。這意味著無法建立新連線、無法建立新工作執行緒,也無法建立任何新事物。
像 Apache 和 Nginx 這樣的 Web 伺服器特別容易受到影響,因為它們會透過 fork 子進程來處理流量。效能測試顯示,當閒置進程在繁忙的 Web 伺服器上累積時,吞吐量會下降 48%。2019 年,Kubernetes DNS Pod 中一個 Go 語言的通道洩漏,在單一節點上產生了超過 26,000 個閒置進程,填滿了進程表,並導致整個叢集的 DNS 解析崩潰。
下表列出一般程序與殭屍程序之間的關鍵差異:
| 特徵 | 正常程序 | 殭屍進程 |
|---|---|---|
| 狀態符號 | R、S、D 或 T | Z(已終止) |
| CPU / 記憶體 | 活躍使用量 | 0% / 0(已終止) |
| 進程表條目 | 一個插槽 | 一個槽位 |
對 kill -9 | 立即終止 | 無效(已終止) |
| 核心記憶體 | 完整的程序描述符 | 僅最小退出狀態 |
關鍵要點:你無法 kill -9 處理一個殭屍進程。它已經死了。清除它的唯一方法是讓父進程回收它,或是殺死父進程,讓 init (PID 1)能自動繼承並回收它。
如何找出殭屍程序
殭屍進程會在 STAT 欄位顯示為 Z, <defunct> 命令名稱旁。請使用以下指令列出:
ps aux | grep -w Z若要查看父進程 ID(PPID)——這是您進行移除時所需的資訊:
ps -eo pid,ppid,stat,comm | grep -w Z該 top 命令的標頭行也會顯示總殭屍進程數。若要進行快速非互動式檢查:
top -bn1 | grep zombie使用 pstree 追蹤父進程
取得殭屍進程的 PID 後,可追溯至負責的父進程:
pstree -p -s <zombie_pid>這會顯示從 init 到該僵屍進程的完整祖先關係。若 pstree 未安裝, ps auxf 則會提供類似的 ASCII 樹狀圖。
統計殭屍進程以進行監控
一個排除 grep 程序本身的乾淨計數:
ps aux | awk '$8 ~ /Z/ {count++} END {print count+0}'用於故障排除期間的持續監控:
watch -n 1 'ps aux | grep -w Z | wc -l'如何移除殭屍程序
唯有透過收集殭屍進程的退出狀態,才能將其移除。這意味著必須透過其父進程來處理。
1. 找出父程序。
ps -o ppid= -p <zombie_pid>2. 向父進程發出訊號,要求其回收子進程。
kill -SIGCHLD <parent_pid>這會指示父進程對 wait() 來處理任何已終止的子進程。此方法不會造成系統中斷,且適用於行為良好的應用程式。
3. 若 SIGCHLD 無效,則重新啟動服務。
systemctl restart <service_name>4. 若父進程無回應,則終止它。
kill <parent_pid>或者若它忽略 SIGTERM 訊號:
kill -9 <parent_pid>當父進程死亡時, init (PID 1) 會 systemd 收養這些孤兒僵屍進程並立即回收它們。請在生產環境中謹慎操作。終止父進程也會一併終止其所有活躍的子進程。
5. 驗證清理結果。
ps aux | awk '$8 ~ /Z/ {count++} END {print count+0}'若計數為 0,即表示清理完成。
防止僵屍程序
在程式碼中妥善處理子程序
大多數殭屍進程堆積的根本原因在於父進程從未呼叫 wait()。從源頭解決:
- C:設定
signal(SIGCHLD, SIG_IGN);以自動丟棄子程序退出資訊,或使用帶有waitpid(-1, NULL, WNOHANG)以進行非同步回收。 - Python:使用
subprocess.run(),它會自動等待。若使用Popen,請proc.wait()。 - Bash:在
wait於執行背景工作的腳本結尾。
正確設定 systemd
對於由 systemd 管理的服務,以下設定可防止僵屍進程堆積:
KillMode=control-group確保服務停止時,所有子程序會一同終止。TimeoutStopSec讓父進程有時間回收子進程,再由 systemd 發送 SIGKILL 訊號。WatchdogSec自動重新啟動無回應的服務,以處理父程序掛起並停止回收子程序的情況。
監控您的進程表
設定每 15 分鐘執行一次的 cron 工作,用以統計僵屍進程數量,並在數量超過閾值時發出警示:
ps aux | awk '$8 ~ /Z/' | wc -l同時透過將當前計數與 /proc/sys/kernel/pid_max。若超過 80%,請在問題惡化前進行調查。正常運作期間出現少量暫時性殭屍進程無需擔心。若數量持續增加且無法歸零,則表示應用程式存在需修正的錯誤。
結論
殭屍程序是尚未被清理的「死屍」。它們雖不佔用 CPU 或記憶體,卻佔據 PID 資源,而滿載的程序表會導致伺服器無法執行任何有用的作業。
- 使用
ps aux | grep -w Z並透過pstree. - 透過向父進程發送
SIGCHLD至父進程、重新啟動服務,或作為最後手段終止父進程。 - 預防方法包括編寫呼叫
wait(),正確配置 systemd,並監控您的進程表。
若您正在執行高流量的工作負載,且需要具備完整 root 存取權限的可靠基礎架構,FDC 的專用伺服器能讓您完全掌控進程管理與系統設定。

Linux 伺服器加固清單
15 分鐘閱讀 - 2026年5月8日