我正在python中使用subprocess模块运行一些shell脚本。如果shell脚本运行时间很长,我想杀死该子进程。我认为如果将其传递timeout=30
给我的run(..)
陈述就足够了。
这是代码:
try:
result=run(['utilities/shell_scripts/{0} {1} {2}'.format(
self.language_conf[key][1], self.proc_dir, config.main_file)],
shell=True,
check=True,
stdout=PIPE,
stderr=PIPE,
universal_newlines=True,
timeout=30,
bufsize=100)
except TimeoutExpired as timeout:
我已经用一些运行120秒的shell脚本测试了此调用。我期望子进程在30秒后被杀死,但是实际上该进程正在完成120秒脚本,然后引发了Timeout
Exception。现在的问题是如何通过超时杀死子进程?
该文档明确指出应终止该进程:
从文档中获取subprocess.run
:
“
timeout参数传递给Popen.communicate()。如果超时到期,子进程将被杀死并等待。子进程终止后,将重新引发TimeoutExpired异常。”
但是在您的情况下,您正在使用shell=True
,而且我之前也遇到过类似的问题,因为阻塞过程是Shell过程的子过程。
我认为,shell=True
如果适当地分解参数并且脚本具有适当的shebang,则不需要。您可以尝试以下方法:
result=run(
[os.path.join('utilities/shell_scripts',self.language_conf[key][1]), self.proc_dir, config.main_file], # don't compose argument line yourself
shell=False, # no shell wrapper
check=True,
stdout=PIPE,
stderr=PIPE,
universal_newlines=True,
timeout=30,
bufsize=100)
请注意,我可以在Windows上非常轻松地重现此问题(使用Popen
,但这是同一回事):
import subprocess,time
p=subprocess.Popen("notepad",shell=True)
time.sleep(1)
p.kill()
=>记事本保持打开状态,可能是因为它设法脱离了父shell进程。
import subprocess,time
p=subprocess.Popen("notepad",shell=False)
time.sleep(1)
p.kill()
=>记事本在1秒后关闭
有趣的是,如果将其删除time.sleep()
,kill()
即使shell=True
可能成功杀死正在启动的外壳,它也可以正常工作notepad
。
我并不是说您有完全相同的问题,我只是shell=True
出于多种原因证明这是邪恶的,而无法中止/超时则是另一个原因。
但是, 如果
你需要shell=True
一个理由,你可以使用psutil
杀到底所有的孩子。在这种情况下,最好使用它,Popen
以便直接获取进程ID:
import subprocess,time,psutil
parent=subprocess.Popen("notepad",shell=True)
for _ in range(30): # 30 seconds
if parent.poll() is not None: # process just ended
break
time.sleep(1)
else:
# the for loop ended without break: timeout
parent = psutil.Process(parent.pid)
for child in parent.children(recursive=True): # or parent.children() for recursive=False
child.kill()
parent.kill()
(资料来源:如何从python中杀死进程和子进程?)
该示例也会杀死记事本实例。
问题内容: 我想尽可能快地重复执行子过程。但是,有时该过程将花费很长时间,因此我想取消它。我使用signal.signal(…),如下所示: 但有时这段代码将尝试阻止下一轮执行。停止test / home / lu / workspace / 152 / treefit / test2超时/ bin / sh:/ home / lu / workspace / 153 / squib_driver
问题内容: 我需要制作一个从用户获取以下内容的脚本: 1)进程名称(在Linux上)。 2)此进程写入的日志文件名。 它需要终止该进程并确认该进程已关闭。将日志文件名更改为带有时间和日期的新文件名。然后再次运行该过程,确认它已启动,以便继续写入日志文件。 先谢谢您的帮助。 问题答案: 您可以使用以下命令检索给定名称的进程ID(PID): 希望这可以帮助
问题内容: 我从python脚本生成了5个不同的进程,如下所示: 我的问题是,当父进程(主脚本)以某种方式被杀死时,子进程继续运行。 当父进程被杀死时,有没有办法杀死这样生成的子进程? 编辑:我正在尝试: 但这似乎不起作用 问题答案: 我自己也遇到了同样的问题,我有以下解决方案: 打电话之前,您可以设置。然后如此处所述python.org multiprocessing 进程退出时,它将尝试终止其
问题内容: 例如从bash: 仅杀死父进程。 问题答案: 当您将 负 PID传递给时,它实际上会通过该(绝对)数字将信号发送到过程 组 。您可以在Python中完成与之等效的操作。
问题内容: 我有一个程序生成并与CPU繁重,不稳定的进程通信,而不是由我创建的。如果我的应用程序崩溃或被杀死,我也希望子进程也被杀死,因此用户不必跟踪它们并手动杀死它们。 我知道以前已经讨论过该主题,但是我已经尝试了所有描述的方法,但似乎没有一种方法能够经受住测试的考验。 我知道这是有可能的,因为终端一直在这样做。如果我在终端中运行某些程序并杀死该终端,则这些东西总是会死掉。 我试过了,双叉和。不
问题内容: 我在Python中使用子进程包运行一个子进程,以后需要杀死它。但是,子流程包的文档指出,terminate()函数仅从2.6起可用。 我们正在运行带有2.5的Linux,并且出于向后兼容的原因,我无法升级到2.6,替代品是什么?我猜这些功能是某些事情的便捷方法。 问题答案: 您在进程pid上调用os.kill。 您还可以,因为您使用的是Linux。Windows用户很不走运。