僵尸进程在ps中STAT列为Z,不占资源但占PID;需通过kill -s SIGCHLD向父进程发信号或重启父服务来清理,最终由init回收;预防需父进程正确调用wait/waitpid或使用tini等容器init。

识别僵尸进程的常用方法
僵尸进程在 ps 命令输出中表现为 STAT 列为 Z(或 Z、<defunct></defunct>),它不占用 CPU 或内存,但会持续占用进程 ID 和内核进程表项。最直接的检查方式是:
-
ps aux | grep 'Z'—— 快速列出所有 Z 状态进程,关注 PID 和 PPID(父进程 ID) -
ps -eo pid,ppid,stat,comm | grep 'Z'—— 更清晰地显示关键字段,避免误匹配 -
top命令顶部会明确提示当前僵尸进程数量,如1 zombie - 统计总数:
ps -e -o stat --no-header | grep -c 'Z'
定位并处理父进程
僵尸进程本身无法被 kill,真正需要干预的是它的父进程。清理的核心逻辑是:让父进程调用 wait() 或 waitpid() 回收子进程状态。
- 通过
ps -p <Z_PID> -o ppid=获取父进程 PID - 尝试向父进程发送
SIGCHLD信号:kill -s SIGCHLD <PPID>,部分程序会响应并自动回收 - 若父进程是服务类进程(如 nginx、apache、自研守护进程),优先重启该服务:
systemctl restart xxx或kill -TERM <PPID>后重新拉起 - 极端情况下,父进程已僵死或设计缺陷严重,可终止父进程,系统会将其子进程(含僵尸)交由
init(PID 1)接管并自动回收
验证是否清理成功
执行完上述操作后,需确认僵尸是否消失:
- 再次运行
ps aux | grep 'Z',输出应为空 - 观察
top中 zombie 计数是否归零 - 检查
/proc/<PPID>/status中的Children字段或Threads是否异常,辅助判断父进程是否仍在派生未回收子进程
预防僵尸进程反复出现
治标更要治本。长期运行的服务或自研程序若频繁产生僵尸,说明其子进程管理存在缺陷:
- 开发阶段确保父进程对每个
fork()都配对调用wait()或waitpid();使用sigaction()设置SIGCHLD处理函数是更健壮的做法 - Shell 脚本中避免无等待地启动后台子进程,例如
./task.sh &后应跟wait或记录 PID 并轮询 - 监控手段:定期采集
ps -eo stat | grep -c 'Z'指标,接入 Prometheus 或 Zabbix,异常时触发告警 - 容器环境中,注意 init 进程缺失问题——Docker 默认使用
/bin/sh -c作为 PID 1,无法自动收割子进程,建议用tini或dumb-init作为容器入口点


















