在 Ubuntu(以及所有 Linux 系统)里,僵尸进程(Zombie / defunct)本质上不是 bug,而是进程生命周期的正常现象。它的出现通常说明:子进程已经结束,但父进程还没有回收它的状态信息。
下面从原理、常见原因、是否正常、以及如何处理 4 个角度说明。
进程结束的正常流程
exit() 或被信号杀死wait() / waitpid() 读取这个状态僵尸进程的本质
子进程已经死了,但父进程还没“收尸”
此时进程:
Z(zombie)wait()(最常见)很多程序:
示例(C):
pid_t pid = fork();
if (pid == 0) {
// 子进程
exit(0);
}
// 父进程没调用 wait()
用 ps 看:
ps aux | grep Z
即使父进程本意是想回收,但如果:
SIGCHLD也可能导致僵尸进程累积。
Ubuntu 默认是 systemd,理论上它会回收孤儿进程:
systemd
但:
也可能出现僵尸。
常见场景:
fork() 的网络服务例如:
cmd & 但没 waitsubprocess.Popen 但没 communicate()ps aux | awk '$8=="Z"'
或:
ps -eo pid,ppid,stat,cmd | grep Z
你会看到:
PID PPID STAT CMD
1234 1000 Z [xxx] <defunct>
看 PPID,那个进程就是造成僵尸的元凶。
❌ 不能 kill 僵尸进程
它已经死了,kill 没用
✅ 正确做法:
wait()SIGCHLDkill -HUP 父进程PID
或:
systemctl restart 服务名
signal(SIGCHLD, SIG_IGN);
或:
waitpid(-1, NULL, WNOHANG);
subprocess.Popen.communicate()
cmd &
wait
Ubuntu 出现僵尸进程,不是系统问题,而是“父进程没回收子进程”的正常现象。
如果你愿意,可以把:
ps -ef贴出来,我可以帮你具体判断是哪个程序造成的、该不该管、怎么修。