在 Ubuntu(以及一般 Linux 系统)中,**僵尸进程(Zombie Process)**本质上是“已经结束但父进程还没回收状态的进程”。它们本身不占 CPU/内存,但会占用 PID,多了可能导致系统无法创建新进程。
下面从原理 → 预防方法 → 排查处理三个层面讲。
进程结束流程:
exit()wait() / waitpid() 回收僵尸进程的根因:
signal(SIGCHLD, SIG_IGN); // 忽略 SIGCHLD,内核自动回收
或
while (waitpid(-1, NULL, WNOHANG) > 0);
import signal
signal.signal(signal.SIGCHLD, signal.SIG_IGN)
或使用:
subprocess.Popen(..., start_new_session=True)
./child &
wait
常见错误:
while True 但不处理子进程system() / popen() 但不关闭✅ 推荐:
Ubuntu 默认用 systemd:
[Service]
Type=simple
ExecStart=/opt/app/bin/server
Restart=on-failure
systemd 会:
daemon() 或 setsid防止子进程依附 shell:
setsid();
或
nohup app &
disown
ulimit -u 1000
防止 PID 被僵尸占满。
ps aux | awk '$8 ~ /Z/'
或
top → 看 Tasks: x zombie
ps -o pid,ppid,stat,cmd -p <僵尸PID>
✅ 杀父进程(不是杀僵尸)
kill -9 父PID
之后僵尸会被 init / systemd 回收。
❌ 不要直接 kill -9 僵尸PID(无效)
SIGCHLD& 和 nohup如果你愿意,可以:
我可以帮你具体改造成“无僵尸”版本。