如何清理 Linux 僵尸进程?

1. 什么是僵尸进程?

Linux 中的僵尸进程(Zombie processes)有时也被称为失效或死亡进程。它们是已执行完毕的进程,但其条目并未从进程表中删除。

2 进程状态

Linux 会维护一个进程表,其中包含所有正在运行的进程及其状态。下面简要介绍一下各种进程状态: 

(1)Running (R): 表示这些进程目前正在运行或可运行,用字母R表示。需要说明:进程是R状态,不代表正在运行,代表可被调度。换句话说,进程只有是R状态才可被调度,其他状态要先转为R状态,才能被 OS 调度;

(2)Waiting (S/D): 表示这些进程正在等待事件完成或某种资源就绪,用字母S/D表示,等待可以是可中断休眠S(interruptible sleep) 或不中断休眠D(uninterruptible sleep);

(3)Stopped (T): 可以通过发送SIGSTOP信号给进程来停止(T)进程。这个被暂停的进程可以通过发送SIGCONT信号让进程继续运行。

(4)Zombie (Z): 一个比较特殊的状态。当子进程退出并且父进程没有读取到子进程退出的返回代码时,就会产生僵死(尸)进程。僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入 Z状态。

3 僵尸进程是如何产生的?

当一个进程完成其工作时,Linux 内核会通过发送 SIGCHLD 信号通知其父进程。然后,父进程执行 wait() 系统调用,读取子进程的状态并读取其退出代码。这会清除进程表中子进程条目,从而结束进程。但是,如果父进程没有在创建子进程时执行wait()系统调用,就不会进行适当的清理。在这种情况下,父进程无法监控子进程的状态变化,最终会忽略SIGCHLD信号。这将导致已完成进程的僵尸状态留在进程表中,从而使其作为僵尸进程出现在进程列表中。另一种情况是,父进程无法处理或接收来自子进程的SIGCHLD信号,这种情况也会导致僵尸的产生。

4  搜索僵尸进程

使用ps命令来检索僵尸进程列表:

ps ux

从输出中可以看出,STAT 列中的 Z 即为僵尸进程状态,或者使用 awk 命令根据 Z 进程状态进一步过滤输出:

另一种方法是使用 top 命令:

top 除了输出其他详细信息外,还可以在输出顶部的摘要中看到僵尸进程的数量。

5 清理僵尸进程

我们无法真正杀死僵尸进程,因为本身它已经结束了。但是,可以使用一些方法来清理僵尸进程。

5.1 使用 SIGCHLD 信号

可以手动向僵尸进程的父进程发送SIGCHLD信号。这样,父进程就会主动触发wait()系统调用,从而从进程表中清除已失效的子进程。

找到僵尸进程的父进程 PID: 

这里 108 表示僵尸进程 PID,103 表示其父进程 PID,接下来,可以使用kill命令向父进程发送SIGCHLD信号:

kill -s  SIGCHLD 103

不过,并不能保证向父进程发送SIGCHLD信号就能杀死僵尸进程。只有在父进程可以处理SIGCHLD信号的情况下,它才会起作用。

5.2 kill 父过程

如果上一节的方法无法清除失效进程,就需要考虑杀死其父进程:

kill -9103

但是,杀死父进程会影响其所有子进程。因此,应该格外谨慎,在杀死父进程之前必须确定其影响。如果存在大量僵尸进程,或者僵尸进程的父进程是 init 进程(pid=1),可以考虑重启系统来清除失效进程。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容