Linux 中的殭屍進程:尋找、移除、預防

15 分鐘閱讀 - 2026年5月19日

hero section cover
目錄
  • Linux 中的殭屍程序:如何查找與移除
  • 為何伺服器上的殭屍進程至關重要
  • 如何找出殭屍程序
  • 如何移除殭屍程序
  • 防止僵屍程序
  • 結論
分享

學習如何在 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 或 TZ(已終止)
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 中的殭屍進程:尋找、移除、預防

Linux 中的殭屍進程:尋找、移除、預防

學習如何在 Linux 中識別、移除和預防殭屍進程。伺服器管理員的指令、程式碼修正和監控技巧。

15 分鐘閱讀 - 2026年5月19日

Linux 伺服器加固清單

15 分鐘閱讀 - 2026年5月8日

更多文章