如何在python中彻底杀死子进程

时间:2017-01-31 15:34:43

标签: python linux zombie-process defunct

我们正在使用python进程来管理长时间运行的python子进程。偶尔需要杀死子程序。 kill命令不会完全终止进程,只会使其失效。

运行以下脚本演示了此行为。

import subprocess
p = subprocess.Popen(['sleep', '400'], stdout=subprocess.PIPE, shell=False)

p = subprocess.Popen('sleep 400', stdout=subprocess.PIPE, shell=True)

将创建子流程。

p.terminate() 
p.kill()

对此过程不执行任何操作。由ps aux | grep sleep

展示
$ ps aux| grep 'sleep'
User       8062  0.0  0.0   7292   764 pts/7    S    14:53   0:00 sleep 400

这个过程没有被杀死/已经不复存在。使用subprocess.call()函数以'kill'pid作为参数将发出kill命令。

subprocess.call(['kill', str(p.pid)])

这会扼杀这个过程但现在已经不存在了。

$ ps aux | grep 'sleep'
User       8062  0.0  0.0      0     0 pts/7    Z+   14:51   0:00 [sleep] <defunct>

如果队列运行的时间足够长,它最终会达到最大进程数,还是最终会收到已解散的进程并且没问题呢?

如果答案是前者,如何在不杀死父进程的情况下处理python中的defunct进程?

有没有更好的方法来杀死进程?

2 个答案:

答案 0 :(得分:7)

这里有两个主要问题:

第一个问题:如果你正在使用shell=True,那么你就是要杀死运行流程的 shell ,而不是流程本身。随着父母被杀,孩子的过程就会不复存在,也不会立即被杀死。

在您的情况下,您使用的是非内置的sleep,因此您可以删除shell=TruePopen会产生实际的进程ID:{{ 1}}会起作用。

你可以(并且你应该)在大多数时候避免使用p.terminate(),即使它需要额外的python编码工作(将2个命令组合在一起,重定向输入/输出,所有这些情况都可以很好地处理一个或者多个shell=True 没有 Popen

并且(第二期)如果在该修复后终止该流程仍然无效,您可以致电shell=True(来自this问题)。似乎调用p.wait()还不够。 terminate对象需要进行垃圾回收。

答案 1 :(得分:2)

您应该在终止子进程后调用p.wait() - 清除进程表。这应该删除僵尸进程(defunct状态)