如何在Linux上杀死一个僵尸进程

1,216 阅读3分钟

这里有一个像纪元一样古老的故事,自从有了C和Unix,以及(后来的)Linux,我们就有了_僵尸_。具体来说,有一些进程会被标记为_僵尸进程_。一些人误解,另一些人忽视,而且对我们许多人的努力免疫,试图将这些进程kill ,但没有取得多大成功。这是为什么呢?

什么是Linux中的进程?

当Linux中的一个程序被执行时,这一切都开始了,当它被执行时,它的运行实例被称为进程。你可以用ps 命令查看你的Linux环境中的所有进程。

$ ps -ax
        PID TTY         STAT   TIME COMMAND
        1 ?     Ss      0:01 /usr/lib/systemd/systemd rhgb --switched-root --sys
        2 ?     S       0:00 [kthreadd]
        3 ?     I<      0:00 [rcu_gp]
        4 ?     I<      0:00 [rcu_par_gp]

有时一个进程启动另一个进程,使第一个进程成为第二个进程的父进程。pstree 命令是一个伟大的工具,它允许你看到你系统上的进程的 "谱系"。

$ pstree -psn
systemd(1)─┬─systemd-journal(952)
        ├─systemd-udevd(963)
        ├─systemd-oomd(1137)
        ├─systemd-resolve(1138)
        ├─systemd-userdbd(1139)─┬─systemd-userwor(12707)
        │                     ├─systemd-userwor(12714)
        │                     └─systemd-userwor(12715)
        ├─auditd(1140)───{auditd}(1141)
        ├─dbus-broker-lau(1164)───dbus-broker(1165)
        ├─avahi-daemon(1166)───avahi-daemon(1196)
        ├─bluetoothd(1167)

每个进程在系统中都被分配一个编号。进程ID号1被分配给启动过程中执行的第一个进程,PID1之后的每个后续进程都是它的后代。PID1进程就是_init_,在大多数新版本的Linux中,它只是一个指向systemd 程序的符号链接。

用kill命令结束一个进程

你可以用kill 命令来终止Linux系统中的进程_。_ 尽管名字是这样的,但kill 命令和一组其他的命令,如pkillkillall 被编写/设计为向一个或多个进程发送SIGNALS。当没有指定时,它发送的默认SIGNAL是终止进程的SIGTERM信号。

当一个父进程死亡或被杀死,而其子进程没有跟随其父进程的死亡,我们称该进程为_孤儿进程_。

另一方面,"僵尸进程 "不能被杀死。你可能会问为什么?嗯,因为它们已经死了

每一个子进程,当被终止时,都会成为一个僵尸进程,然后被父进程删除。当进程退出其存在并释放它所使用的资源时,它的名字仍然在操作系统的进程表中。这时,父进程的工作就是把它的名字从进程表中删除。当它失败时,我们就有了僵尸进程,它不再是一个真正的进程,而只是操作系统进程表上的一个条目。

这就是为什么试图对一个失效的(僵尸)进程执行kill 命令,即使使用-9 (SIGKILL)选项也不会起作用,因为没有什么可杀。

因此,要杀死一个僵尸进程,例如从进程列表(进程表)中删除其名称,你必须杀死其父进程。例如,如果PID 5878是一个僵尸进程,而它的父进程是PID 4809,那么要杀死僵尸进程(5878),就必须结束父进程(4809)。

$ sudo kill -9 4809  #4809 is the parent, not the zombie

我对僵尸的最后一句警告:在杀死父进程时要非常小心,如果一个进程的父进程是PID 1,而你清理了它,你就会重启自己!