僵尸进程不占cpu或内存但占用pid,导致“resource temporarily unavailable”;需用ps -eo pid,ppid,state,comm | awk '$3=="z"'等命令精准识别,并溯源父进程排查wait()缺失、僵死或信号处理缺陷,切勿kill -9或乱调内核参数。

僵尸进程本身不占CPU或内存,但会持续占用PID资源,积压过多会导致新进程无法创建,报“Resource temporarily unavailable”。排查关键不是杀它,而是找出谁没尽责收尸——也就是它的父进程。
快速识别僵尸进程的可靠方法
别依赖top默认视图,它默认隐藏Z状态进程。最稳的方式是用ps直接筛选:
- ps -eo pid,ppid,state,comm | awk '$3=="Z" {print}' —— 只输出真正状态为Z的行,干净无干扰
- ps aux | grep 'Z ' —— 注意Z后面带空格,避免误匹配含Z字母的命令名
- 看到
<defunct></defunct>字样也代表僵尸,但以Z状态为准,更准确
顺藤摸瓜:定位父进程和服务源头
知道僵尸PID只是开始,得查清楚谁生的它、谁该负责回收:
- 用ps -o ppid= -p Z_PID(注意等号前有空格)拿到父进程PID
- 再执行ps -p PPID -o pid,ppid,comm,args,重点看comm列(如nginx、python、supervisord)和args列(启动参数,可判断是否为业务服务)
- 若父进程是systemd(PID 1),运行systemctl status --all | grep -A5 -B5 Z_PID查最近日志线索
- 容器环境先docker inspect container_id | grep -i pid确认宿主机映射关系,再查对应PID
常见父进程失职原因与应对方向
父进程不调wait()通常不是故意忽略,而是卡在逻辑里:
- 守护进程如supervisord配置了
autorestart=false,子进程异常退出后未监听SIGCHLD信号 - 父进程自身已僵死(ps查不到或状态为X/K),此时重启对应服务(如
systemctl restart nginx)可让init接管并清理遗孤 - 自研程序写了SIGCHLD处理函数,但漏了
WNOHANG标志或未循环调用waitpid(),导致只回收一次就停住
哪些操作绝对要避开
僵尸进程不能被kill -9,因为它早已终止,只剩内核里的一个条目。强行干预反而引发更大风险:
- 不要
echo 1 > /proc/sys/kernel/panic_on_oops或修改其他内核参数试图“强制清理”——这会让系统行为不可控 - 不要直接kill父进程,除非你确认它已无响应且不影响核心业务;否则可能中断正在运行的服务
- 别迷信htop或pstree单独显示Z状态,它们可能因刷新延迟或权限问题漏报,仍应以ps结果为准










