在 CentOS(以及其他 Linux 发行版)中,僵尸进程(Zombie / defunct 进程) 的本质是:进程已经退出,但父进程还没有调用 wait()/waitpid() 回收它的退出状态。僵尸进程不占 CPU、不占内存,但会占用 PID 表项。
下面按“发现 → 定位父进程 → 处理”来说明。
ps 查看ps -ef | grep defunct
或
ps aux | awk '$8 ~ /Z/'
僵尸进程在 STAT 列通常显示为:
Z (zombie)
示例:
user 12345 12300 0 10:00 ? 00:00:00 [process] <defunct>
其中:
12345:僵尸进程 PID12300:父进程 PPID(关键)toptop
在任务统计区会看到:
Tasks: 210 total, 1 zombie
按 f 可以显示更多列,如 PPID、STAT。
/proc 精确检查for p in /proc/[0-9]*; do
if [ "$(cat $p/stat 2>/dev/null | awk '{print $3}')" = "Z" ]; then
echo "Zombie PID: $(basename $p)"
fi
done
僵尸进程无法直接 kill,必须处理它的父进程。
ps -o pid,ppid,stat,cmd -p <僵尸PID>
示例:
ps -o pid,ppid,stat,cmd -p 12345
输出:
PID PPID STAT CMD
12345 12300 Z [process] <defunct>
→ 父进程是 12300
ps -p 12300 -o pid,ppid,cmd,stat
或:
cat /proc/12300/cmdline
SIGCHLDwait() / waitpid()systemctl restart <服务名>
如果父进程是普通服务:
kill -TERM 12300
# 或
kill -9 12300
父进程死后:
wait() 回收如果父进程是 1:
ps -o pid,ppid,cmd -p <僵尸PID>
→ PPID = 1
说明:
| 原因 | 说明 |
|---|---|
| 父进程未 wait 子进程 | 最常见 |
| 忽略 SIGCHLD | 错误写法 |
| 多线程程序中主线程退出 | 子线程变僵尸 |
| 第三方程序 bug | Java / Python / C 服务 |
| Docker / 容器 init 问题 | 容器内 PID 1 处理不当 |
ps -eo pid,ppid,stat,cmd | awk '$3=="Z"'
或一键脚本:
ps -eo pid,ppid,stat,cmd | awk '$3=="Z"{print "Zombie:",$1,"Parent:",$2}'
如果你愿意,可以把:
ps -ef | grep defuncttop 的输出贴出来我可以帮你具体定位是哪一个服务或程序导致僵尸进程。