终止正在运行的子进程调用

Posted

技术标签:

【中文标题】终止正在运行的子进程调用【英文标题】:Kill a running subprocess call 【发布时间】:2013-05-27 19:47:58 【问题描述】:

我正在 Python 上使用subprocess 启动一个程序。

在某些情况下,程序可能会冻结。这是我无法控制的。我唯一能从它启动的命令行做的是 CtrlEsc 快速杀死程序。

有什么方法可以用subprocess 来模拟吗?我正在使用subprocess.Popen(cmd, shell=True) 启动程序。

【问题讨论】:

【参考方案1】:

以下命令对我有用

os.system("pkill -TERM -P %s"%process.pid)

【讨论】:

【参考方案2】:

尝试将您的 subprocess.Popen 调用包装在 try except 块中。根据您的进程挂起的原因,您可能能够干净地退出。以下是您可以检查的异常列表:Python 3 - Exceptions Handling

【讨论】:

【参考方案3】:

您的问题不太清楚,但是如果我假设您即将启动一个进入僵尸的进程,并且您希望能够在脚本的某些状态下控制它。如果是这种情况,我建议您:

p = subprocess.Popen([cmd_list], shell=False)

这并不是真正建议通过shell。 我建议你使用 shell=False,这样可以减少溢出的风险。

# Get the process id & try to terminate it gracefuly
pid = p.pid
p.terminate()

# Check if the process has really terminated & force kill if not.
try:
    os.kill(pid, 0)
    p.kill()
    print "Forced kill"
except OSError, e:
    print "Terminated gracefully"

【讨论】:

- p.pid 是 Popen 实例的属性,而不是方法 - OSError 究竟是什么时候引发的?即使对于简单的 Popen 调用( subprocess.Popen("ls", shell=False)),我似乎也无法使用 except 语句。 没错,pid是一个属性,应该是打字错误。对于 OSError,如果 pid 不再存在,则会在 os.kill(pid, 0) 步骤引发异常 - p.terminate() 已成功终止 pid ;-) 是否需要os.killp.kill?一个还不够吗?【参考方案4】:

您可以使用两个信号来终止正在运行的子进程调用,即 signal.SIGTERM 和 signal.SIGKILL;例如

import subprocess
import os
import signal
import time
..
process = subprocess.Popen(..)
..
# killing all processes in the group
os.killpg(process.pid, signal.SIGTERM)
time.sleep(2)
if process.poll() is None:  # Force kill if process is still alive
    time.sleep(3)
    os.killpg(process.pid, signal.SIGKILL)

【讨论】:

代替sleep(2) + poll 您可以使用wait(2) 超时,如果进程快速退出,这不会浪费两秒钟。此外,您可以使用process.terminateprocess.kill 代替os.killpg【参考方案5】:

嗯,subprocess.Popen() 返回的对象有几个可能有用的方法:Popen.terminate()Popen.kill(),它们分别发送 SIGTERMSIGKILL

例如...

import subprocess
import time

process = subprocess.Popen(cmd, shell=True)
time.sleep(5)
process.terminate()

...将在五秒后终止进程。

或者你可以使用os.kill()发送其他信号,比如SIGINT模拟CTRL-C,用...

import subprocess
import time
import os
import signal

process = subprocess.Popen(cmd, shell=True)
time.sleep(5)
os.kill(process.pid, signal.SIGINT)

【讨论】:

在 Windows kill = terminate 和信号的工作方式不同。 此答案缺少对 process.wait() 的调用 — ***.com/questions/55052055/…【参考方案6】:
p = subprocess.Popen("echo 'foo' && sleep 60 && echo 'bar'", shell=True)
p.kill()

查看subprocess 模块上的文档以获取更多信息:http://docs.python.org/2/library/subprocess.html

【讨论】:

应该在彻底杀死它之前尝试终止。 尝试终止然后杀死,子进程仍然运行!! 这可能是因为 shell=True 请注意,除非您在杀死进程后等待(),否则您将创建僵尸进程,ResourceWarning: subprocess 512574 is still running***.com/questions/55052055/…

以上是关于终止正在运行的子进程调用的主要内容,如果未能解决你的问题,请参考以下文章

在父进程收到终止信号并退出后,让 system() 生成的子进程继续运行

无法在 Windows 上使用 Python 终止正在运行的子进程

django celery 终止任务的子进程

subprocess:删除Windows中的子进程

如何在 python 中杀死使用 subprocess.call 调用的子进程? [复制]

从分离的子进程获取输出