如何杀死 Linux 中的僵尸进程
据传说,魂去身存还能活动的肉体名叫僵尸,常常出没于深山老林之中。然而在现代,伴随着 C 语言和 Unix 系统的诞生,赛博僵尸开始活跃于每一台电脑中。或者说,在使用电脑的过程中,有那么一些进程由于种种原因,变成了虽然已经被自我杀死但还仍然占用着资源的僵尸进程。与此相对的还有已经失去父进程、无法被正常调用本应该死亡但还在运行的孤儿进程。关闭孤儿进程是比较简单的一件事,但检索和 kill 僵尸进程要困难许多。
如何理解进程
程序们被执行的时候,它们会叫出一系列进程作为小弟,去具体跑腿来实现功能。比如我们可以用 ps 命令来查看当前的所有进程。
当然,不仅是程序会创建新进程,进程也可以创建新进程,这种情况下就会产生类似树形的结构,我们可以用 pstree 来查看进程树的情况。
更大的进程树会像这样:
可以看到每个进程都在系统中有一个编号,即 pid。pid 1的进程就是系统引导中执行的第一个进程,也就是 init 进程。在新版本的 Linux 中通常叫做 systemd。
使用 kill 来杀死进程
kill 命令是 Linux 系统中的一把最锋利的剑,你可以用它来终止 Linux 系统中所有指定的进程。而只删除一个进程会比较危险,要小心它的家人依旧存活在你的系统中,通过占用资源来报复你。可以尝试 killall 指令,它会帮助你下“诛九族”的命令。
如果单独杀掉父进程而子进程没能自动结束,子进程就变成了孤儿进程,但只要通过 ps 命令搜索到它的 pid,依旧可以简单的结束掉它们。
如何杀死僵尸进程
那么僵尸进程又有什么特殊的呢?因为它们已经死过一次了,所以不能再杀掉了。
如果一个子进程自然终止,它们都会变成临时的僵尸进程,直到父进程通过代码释放掉它们本来所占用的资源。但如果父进程这一步失败或被忽略了,这个子进程就变成了真正的僵尸进程,虽然不在运行,但还是空占着资源。所以你普通地用 kill 命令来结束掉它们的时候,一般情况下是不起作用的。
那么要怎么杀掉它们呢?答案是结束掉它们的父进程。首先用 ps 指令来找到需要杀死的僵尸进程,然后用 pstree 指令寻找它们的父进程,结束掉父进程,就可以实现目标了。假设 pid 827 是我们要结束的僵尸进程,而 pid 749是它的父进程,我们可以
$ sudo kill -9 749
来结束掉它们的生命。
结束掉父进程是一个很方便的做法,但要注意最极端的情况:父进程的 pid 是 1。这种时候杀掉父进程,它会自动重启,变成不死的僵尸 🙁
参考资料: