杀死僵尸进程的另一种方式


19

我刚刚注意到CentOS 6.8(Final)上有一些僵尸进程,试图杀死它们,但它们仍然存在:

[root@host user]# ps -ef | grep git
tomcat     746     1  0 Jul18 ?        00:00:00 git clone https://github.com/angular/bower-angular.git -b v1.3.20 --progress . --depth 1
tomcat     747   746  0 Jul18 ?        00:00:00 [git-remote-http] <defunct>
root     20776 20669  0 09:03 pts/3    00:00:00 grep git
tomcat   29970     1  0 Jul18 ?        00:00:00 git clone https://github.com/components/jqueryui.git -b 1.12.0 --progress . --depth 1
tomcat   29971 29970  0 Jul18 ?        00:00:00 [git-remote-http] <defunct>

[root@host user]# kill 746 747 29970 29971

[root@host user]# ps -ef | grep git
tomcat     746     1  0 Jul18 ?        00:00:00 git clone https://github.com/angular/bower-angular.git -b v1.3.20 --progress . --depth 1
tomcat     747   746  0 Jul18 ?        00:00:00 [git-remote-http] <defunct>
root     21525 20669  0 09:26 pts/3    00:00:00 grep git
tomcat   29970     1  0 Jul18 ?        00:00:00 git clone https://github.com/components/jqueryui.git -b 1.12.0 --progress . --depth 1
tomcat   29971 29970  0 Jul18 ?        00:00:00 [git-remote-http] <defunct>

如您所见,它们已经运行了两个月,而且如果它们对人体无害,我也会摆脱它们,还有其他替代方法可以杀死僵尸吗?


1
你有尝试过kill -9吗?
Ipor Sircer '16

7
只有74729971是僵尸进程。其他人可能被锁起来,但尚未死亡。
roaima

似乎您在tomcat上运行的某些代码中存在错误……
蜘蛛鲍里斯(Boris)

Answers:


8

如Heemayl所述,您实际上无法杀死僵尸。已经死了……

但是,您面临的问题看起来像该git clone命令的问题。它被卡住了。可能超时或以其他方式失败?这往往是因为一些I / O,一个进程被卡住的地步SIGTERM,并SIGINT不会工作。

要杀死它,在这种情况下,您想使用-9命令行选项。这意味着发送SIGKILL信号。您实际上-KILL也可以使用。

[root@host user]# kill -KILL 746 29970

要获取可用信号列表,请使用list命令行选项。

[root@host user]# kill -l

这会显示数字和名称(并且您会看到#9表示SIGKILL。)


1
实际上kill -KILL,这是唯一能够关闭这些进程的命令,因此,我将接受@Alexis Wilke的回答。但可以肯定的是,我想对@heemayl快速,明智且非常有用的答案+1表示感谢。感谢大家
lese

39

您无法杀死僵尸(进程),它已经死了。它只是在等待其父进程执行wait(2)并收集其退出状态。除了进程表条目外,它不会占用系统上的任何资源。

您可以发送SIGCHLD给其父项,以告知其子项之一已终止(即要求其收集子项的退出状态)。该信号可以忽略(默认):

kill -CHLD <PPID>

(替换<PPID>为父级的实际PID。)

或者,您可以杀死父进程,以便init(PID 1)继承僵尸进程并正确获得它(init继承任何孤儿并wait(2)定期执行的主要任务之一)。但是不建议杀死父母。通常,创建僵尸进程表示存在编程问题/问题,您应该尝试修复或报告该问题。


8
您可以将SIGCHLD发送给它的父级,以告知它的子级是否已终止(即,请求它收集子级的退出状态),可以忽略此信号(默认值) ,问题在于,如果进程忽略SIGCHLD,则没有僵尸将被创建。因此,如果不忽略SIGCHLD,并且没有收获僵尸,则该过程可能是越野车,或是不在乎僵尸孩子。鉴于存在问题的过程是git clone ...,我敢打赌它根本不在乎僵尸孩子,因为这是一个(希望)短暂的过程,可以完成工作然后退出。
安德鲁·亨利

1
@AndrewHenle:尽管大多数情况都是这样,但是默认的动作(SIG_DFLSIGCHILD也忽略了它,但是在这种情况下,僵尸肯定不会自动收割。
R.,

@R 尽管大多数情况都是这样,但默认操作(SIG_DFLSIGCHILD也会忽略它,但是在这种情况下,僵尸肯定不会自动收割。 我不确定您指的是什么。您是否指的是问题未得到解决的过程?我没有看到发送SIGCHLD到其SIGCHLD处理程序设置为SIG_IGN(显式或默认)处理程序的进程将如何导致该进程收获任何僵尸。
安德鲁·亨利

1
@AndrewHenle,这次发送一个SIGCHLD可能有效。上一次它可能错过信号或两个孩子同时死亡,并且代码不够聪明,无法同时处理这两次死亡。
亚历克西斯·威尔克

它不会造成伤害,但我不会为此付出任何努力。
Barmar

2

寻找僵尸进程:

ps aux | grep -w Z | grep -v grep

ps -eo stat,ppid | grep -w Z

为了杀死僵尸进程,需要杀死父ID,即PPID:

kill PPID1 PPID2

kill $(ps -eo stat,ppid|grep -w Z|awk '{print $2}'|tr "\n" " ")

0

当父进程死亡时,所有僵尸进程都将被清理。不要为了清理僵尸进程而杀死父进程。重新运行程序时,它将再次出现。通过正确调用“ wait()”或“ waitpid()”系统调用来修复程序。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.