温馨提示×

什么导致ubuntu僵尸进程

小樊
34
2026-09-16 09:01:56
栏目: 智能运维

在 Ubuntu(以及其它 Linux 发行版)里,**僵尸进程(zombie / defunct process)**的本质是:

子进程已经结束运行,但父进程还没有调用 wait() / waitpid() 来回收它的退出状态。

也就是说,僵尸进程不是“死不掉”,而是**“死透了但没人收尸”**。


一、僵尸进程产生的直接原因

1️⃣ 父进程没有回收子进程

这是最常见原因:

  • 子进程调用 exit()
  • 内核保留其 PID、退出码、资源统计
  • 父进程未调用 wait() / waitpid()
  • 进程状态变为 Z(zombie)

示例(C):

pid_t pid = fork();
if (pid == 0) {
    exit(0);  // 子进程退出
}
// 父进程什么都不做

此时子进程就是僵尸。


2️⃣ 父进程阻塞 / 忙 / 写错逻辑

即使父进程“打算”回收,也可能:

  • 主循环卡住
  • 忽略 SIGCHLD
  • 使用错误的 wait 方式
  • 多线程程序中只在某线程 wait

3️⃣ 父进程忽略 SIGCHLD(错误做法)

signal(SIGCHLD, SIG_IGN);

在某些 UNIX 上会防止僵尸,但在 Linux 上不一定可靠,不推荐用于防止僵尸。


4️⃣ 大量短生命周期子进程

如:

  • shell 脚本频繁 fork
  • web 服务每次请求 fork 子进程
  • 定时任务脚本

父进程来不及回收 → 僵尸堆积


二、特殊情况:父进程自身问题

5️⃣ 父进程崩溃前没回收

  • 父进程异常退出
  • 子进程被 init / systemd 接管
  • 通常 不会变僵尸(会被回收)

但若中间层父进程异常,仍可能短期僵尸。


6️⃣ 父进程是 bug 程序

常见于:

  • 自写 daemon
  • 老旧服务
  • 未正确处理子进程退出

三、Ubuntu 中僵尸进程的特点

  • 状态显示为 Z
  • 占用极少资源(不占内存、不占 CPU)
  • 不能被 kill
  • 只能通过 父进程回收或父进程退出 消失

查看方式:

ps -ef | grep defunct
top

看到:

app  1234  1200  0 10:00 ?  00:00:00 [app] <defunct>

四、如何解决 / 避免

✅ 正确做法(开发层面)

  • 父进程调用 wait() / waitpid()
  • 或用 sigaction 处理 SIGCHLD
  • 或使用 system() / popen() 等已封装函数

✅ 运维层面

# 找到僵尸的父进程 PPID
ps -o pid,ppid,stat,cmd -C xxx

# 重启父进程(最常见有效手段)
systemctl restart xxx

⚠️ 不要 kill 僵尸本身,无效


五、常见误区

❌ 僵尸会吃内存
✅ 不会,只保留极小结构体

❌ kill -9 能杀僵尸
✅ 不行,它已经“死”了

❌ 僵尸一定是病毒
✅ 大多数是程序 bug 或设计问题


如果你愿意,可以:

  • ps / top 输出
  • 说明是哪个服务产生僵尸
  • 或贴一段代码

我可以帮你精确定位原因并给修复方案

0