在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