在CentOS系統中,首先需要通過命令定位僵尸進程(狀態為Z或z)。常用命令如下:
ps aux | grep 'Z' 或 ps -ef | grep '[Zz]',可快速篩選出狀態為僵尸的進程;ps -A -o stat,ppid,pid,cmd | grep -e '[Zz]',輸出包含進程狀態、父進程ID(PPID)、進程ID(PID)及命令,便于后續操作。僵尸進程的本質是父進程未回收子進程資源,因此殺死父進程是解決問題的核心方法。操作步驟如下:
kill -s SIGCHLD <父進程ID>,通知父進程回收子進程資源(適用于父進程能正常處理信號的情況);kill -9 <父進程ID>強制終止父進程。此時,僵尸進程會變成孤兒進程,由系統**init進程(PID=1)**自動接管并回收資源。若系統中存在多個僵尸進程,可通過以下命令批量清理:
ps -A -o stat,ppid,pid,cmd | grep -e '[Zz]' | awk '{print 2}' | xargs kill -9
該命令會提取所有僵尸進程的父進程ID,并發送SIGKILL信號強制終止,從而批量清理僵尸進程。
若父進程是自己編寫的程序(如C/C++),可在父進程中調用**wait()或waitpid()**函數,主動等待子進程結束并回收資源。例如:
while(wait(NULL) > 0); // 循環等待所有子進程結束
或在Shell腳本中通過wait命令實現類似功能,避免僵尸進程產生。
父進程可通過設置信號處理函數,忽略SIGCHLD信號(signal(SIGCHLD, SIG_IGN)),此時內核會在子進程退出時自動回收資源,無需父進程手動處理。這種方法適用于不需要跟蹤子進程狀態的場景,能有效預防僵尸進程。
父進程應在創建子進程后,調用wait()或waitpid()函數,及時獲取子進程的退出狀態并回收資源。這是避免僵尸進程的根本方法。
在父進程中設置信號處理函數,捕獲SIGCHLD信號并調用wait()函數。例如:
void sigchld_handler(int sig) {
while(wait(NULL) > 0); // 回收所有子進程
}
signal(SIGCHLD, sigchld_handler);
這種方式能確保父進程及時處理子進程退出事件,避免僵尸進程堆積。
#!/bin/bash
ZOMBIES=$(ps -A -ostat,ppid,pid,cmd | grep -e '[Zz]' | wc -l)
if [ $ZOMBIES -gt 0 ]; then
echo "$(date): 發現$ZOMBIES個僵尸進程,啟動清理!" >> /var/log/zombie.log
ps -A -ostat,ppid,pid,cmd | grep -e '[Zz]' | awk '{print 2}' | xargs kill -HUP
fi