温馨提示×

怎么预防ubuntu僵尸进程

小樊
35
2026-09-16 09:02:57
栏目: 智能运维

在 Ubuntu(以及一般 Linux 系统)中,**僵尸进程(Zombie Process)**本质上是“已经结束但父进程还没回收状态的进程”。它们本身不占 CPU/内存,但会占用 PID,多了可能导致系统无法创建新进程。

下面从原理 → 预防方法 → 排查处理三个层面讲。


一、僵尸进程是怎么产生的?

进程结束流程:

  1. 子进程调用 exit()
  2. 内核保留其退出状态(变成僵尸)
  3. 父进程调用 wait() / waitpid() 回收
  4. 僵尸消失

僵尸进程的根因

  • 父进程没有调用 wait
  • 父进程太忙/写错了
  • 父进程自己挂了但 init 没接管(一般不会)

二、预防僵尸进程的核心方法

✅ 1. 父进程正确回收子进程(最重要)

C / C++ 程序

signal(SIGCHLD, SIG_IGN); // 忽略 SIGCHLD,内核自动回收

while (waitpid(-1, NULL, WNOHANG) > 0);

Python

import signal
signal.signal(signal.SIGCHLD, signal.SIG_IGN)

或使用:

subprocess.Popen(..., start_new_session=True)

Shell 脚本

./child &
wait

✅ 2. 避免“父进程不退出”的设计

常见错误:

  • 父进程是 while True 但不处理子进程
  • system() / popen() 但不关闭

✅ 推荐:

  • 使用进程池
  • 使用 supervisor / systemd 管理

✅ 3. 使用 systemd 管理服务(强烈推荐)

Ubuntu 默认用 systemd:

[Service]
Type=simple
ExecStart=/opt/app/bin/server
Restart=on-failure

systemd 会:

  • 回收子进程
  • 父死子自动清理

✅ 4. 使用 daemon()setsid

防止子进程依附 shell:

setsid();

nohup app &
disown

✅ 5. 限制进程数量(防御性)

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(无效)


四、开发层面 checklist(防僵尸)

  • [ ] 父进程处理 SIGCHLD
  • [ ] 不使用“fork 不 wait”
  • [ ] 服务用 systemd 管理
  • [ ] 长期运行程序定期回收子进程
  • [ ] 不滥用 &nohup

如果你愿意,可以:

  • 贴一段 代码 / 脚本
  • 或说明 是哪种服务(Python / C / Java / Shell)

我可以帮你具体改造成“无僵尸”版本。

0