在 Ubuntu(以及一般 Linux 系统)里,僵尸进程(Zombie / defunct)本质上是已经结束但父进程还没回收其退出状态的进程。它们不占 CPU、内存,但会占用 PID 表项,过多时可能导致系统无法创建新进程。
下面从原理 → 常见原因 → 预防措施 → 应急处理系统说明。
exit())wait() / waitpid()Z(zombie)状态,等待父进程回收✅ 僵尸进程无法被 kill 杀死
只能让父进程回收,或杀死/重启父进程
wait() / waitpid()pid_t pid = fork();
if (pid == 0) {
// child
exit(0);
} else {
wait(NULL); // 回收子进程
}
waitpid() + 非阻塞waitpid(pid, &status, WNOHANG);
signal(SIGCHLD, SIG_IGN)告诉内核:子进程退出后自动回收
signal(SIGCHLD, SIG_IGN);
✅ 适用于:
⚠️ 注意:
父 → 子 → 孙
↓
init 接管
孙子进程退出后由 init 回收,避免 zombie。
command &
disown
或
nohup command &
setsidsetsid command
systemd 会自动回收子进程
[Service]
Type=simple
ExecStart=/opt/app/bin/server
✅ 好处:
import subprocess
subprocess.run(["ls"])
或用:
signal.signal(signal.SIGCHLD, signal.SIG_IGN)
Process.waitFor()waitpidSA_NOCLDWAITstruct sigaction sa;
sa.sa_handler = SIG_IGN;
sigaction(SIGCHLD, &sa, NULL);
ps aux | grep Z
或
top
# 看 Tasks: x zombie
查看父进程:
ps -o pid,ppid,stat,cmd -p <zombie_pid>
kill -9 <zombie_pid> # 无效
kill -9 <parent_pid>
→ zombie 被 init / systemd 回收
systemctl restart xxx
✅ 写程序:
waitpidSIG_IGN SIGCHLD✅ 运维:
& 后台跑如果你愿意,可以:
我可以直接帮你改代码,避免 zombie。