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

use*_*615 4 python linux zombie-process defunct

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

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

import subprocess
p = subprocess.Popen(['sleep', '400'], stdout=subprocess.PIPE, shell=False)
Run Code Online (Sandbox Code Playgroud)

要么

p = subprocess.Popen('sleep 400', stdout=subprocess.PIPE, shell=True)
Run Code Online (Sandbox Code Playgroud)

将创建一个子进程.

p.terminate() 
p.kill()
Run Code Online (Sandbox Code Playgroud)

对这个过程没有任何作用.由...证明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
Run Code Online (Sandbox Code Playgroud)

这个过程没有被杀死/被解散.使用subprocess.call()带有'kill'和pid作为参数的函数将发出kill命令.

subprocess.call(['kill', str(p.pid)])
Run Code Online (Sandbox Code Playgroud)

这会杀死这个过程,但它现在已经不存在了.

$ ps aux | grep 'sleep'
User       8062  0.0  0.0      0     0 pts/7    Z+   14:51   0:00 [sleep] <defunct>
Run Code Online (Sandbox Code Playgroud)

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

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

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

Jea*_*bre 7

这里有两个主要问题:

第一个问题:如果您正在使用shell=True,那么您将杀死运行该进程的shell,而不是进程本身.在其父母被杀害的情况下,子进程将无法立即/不会被杀死.

在你的情况下,你正在使用sleep哪个不是内置的,所以你可以放弃shell=True,Popen并将产生实际的进程ID:p.terminate()将工作.

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

并且(第二期)如果在该修复之后终止该过程仍然不存在,您可以打电话p.wait()(从这个问题).似乎打电话terminate是不够的.该Popen对象需要进行垃圾回收.

  • 谢谢,“p.terminate()”调用后的“p.wait()”修复了它! (2认同)

小智 5

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