僵尸进程(Zombie Process)是已完成执行但未被父进程回收资源的子进程,其状态为Z(Defunct)。虽然僵尸进程本身不消耗大量CPU或内存,但大量存在会占用进程表项,导致系统无法创建新进程,严重时可能引发系统崩溃。
ps命令通过ps命令过滤状态为Z的进程,是最常用的检测方式:
ps aux | grep 'Z' # 列出所有僵尸进程及详细信息(如PID、PPID、命令)
ps -A -ostat,ppid,pid,cmd | grep -e '[Zz]' # 仅显示状态、父进程ID、进程ID和命令
输出中,STAT列为Z的进程即为僵尸进程。
top命令运行top后,按Shift+Z可将僵尸进程置顶,直观查看其数量及资源占用情况(如PID、PPID、状态)。
pstree命令以树状结构展示进程关系,僵尸进程会标注为(zombie),便于快速定位:
pstree -p | grep -i defunct
或直接显示僵尸进程:
pstree -ps | grep -i defunct
/proc文件系统通过读取/proc/[PID]/status文件,查看进程状态是否为Z(如进程ID为1234):
cat /proc/1234/status | grep 'State' # 输出中包含"Z"则表示僵尸进程
僵尸进程的父进程未调用wait()或waitpid()回收资源是根本原因。杀死父进程后,僵尸进程会被**init进程(PID=1)**接管并自动清理:
# 获取僵尸进程的父进程ID(PPID)
ps -o ppid= -p <僵尸进程PID>
# 杀死父进程(-9为强制终止)
kill -9 <父进程PID>
注意:若父进程是系统关键服务(如sshd、httpd),强制杀死可能导致服务中断,需谨慎操作。
SIGCHLD信号若父进程未正确处理子进程退出信号,可发送SIGCHLD(信号编号17)通知其回收资源:
kill -s SIGCHLD <父进程PID>
部分父进程(如Shell、Java应用)会响应此信号,自动清理僵尸子进程。
若僵尸进程由特定服务(如nginx、mysql)产生,重启服务可强制清理所有子进程(包括僵尸进程):
systemctl restart <服务名> # 如systemctl restart nginx
重启前需确认服务允许中断,避免数据丢失。
若僵尸进程由自行编写的程序产生,需修改代码,在父进程中调用wait()或waitpid()等待子进程结束:
#include <sys/wait.h>
#include <stdio.h>
int main() {
pid_t pid = fork();
if (pid == 0) {
// 子进程执行任务
printf("Child process running\n");
sleep(2);
exit(0);
} else {
// 父进程等待子进程结束
int status;
wait(&status); // 回收子进程资源
printf("Child process exited with status: %d\n", WEXITSTATUS(status));
}
return 0;
}
或设置SIGCHLD信号处理函数为SIG_IGN(忽略信号),内核会自动回收子进程资源:
signal(SIGCHLD, SIG_IGN); // 忽略子进程退出信号
父进程必须调用wait()或waitpid()回收子进程资源,这是避免僵尸进程的根本方法。
SIGCHLD信号(适用于不需要子进程状态的场景)在父进程中设置SIGCHLD信号处理函数为SIG_IGN,内核会自动回收子进程资源,无需手动调用wait():
signal(SIGCHLD, SIG_IGN); // 忽略子进程退出信号
适用于后台守护进程或不需要获取子进程退出状态的场景。
编写脚本定期检查僵尸进程数量,超过阈值时自动清理,并通过crontab设置定时任务(如每30分钟执行一次):
#!/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
添加定时任务:
crontab -e
输入:
*/30 * * * * /path/to/zombie_killer.sh
对于频繁出现僵尸进程的应用(如自定义服务、脚本),需检查代码逻辑,确保子进程退出时父进程能及时回收资源,避免因程序缺陷导致僵尸进程累积。
通过以上方法,可有效检测、处理并预防CentOS系统中的僵尸进程,保障系统稳定运行。处理时需注意区分关键进程与非关键进程,避免误操作影响系统服务。