正确关闭 Python 中的子进程 [重复]
Posted
技术标签:
【中文标题】正确关闭 Python 中的子进程 [重复]【英文标题】:Correctly shutting down subprocesses in Python [duplicate] 【发布时间】:2015-12-05 09:35:39 【问题描述】:我有一个 Python 服务器,它通过 subprocess.Popen()
启动多个子进程。当我在服务器上运行特定方法时,我想终止所有这些进程。
我的方法是将所有进程的引用保存在一个列表中......
self.procs.append(subprocess.Popen(shlex.split(cmd)))
...并向所有这些发送中断以关闭它们:
for i, p in enumerate(self.procs) :
p.send_signal(signal.SIGINT)
print 'interrupted ' + str(i)
self.procs = []
但是,这仅适用于某些子流程。例如,在此调用之后不会停止的进程之一是 bash 脚本,该脚本具有用于 SIGINT 信号的trap
函数。如果我手动启动此脚本并通过键盘中断它,它会正确执行陷阱语句并关闭。当服务器改为发送信号时,脚本似乎继续运行。
这里可能出了什么问题?
编辑:我也尝试过使用 SIGTERM 信号,但也没有用。
【问题讨论】:
发送关机的常用信号是SIGTERM
。如果进程仍未关闭,我们通常可能会有“宽限时间”延迟并发送 SIGKILL(如kill -9
)。如果脚本当时正在等待子进程完成,则中断可能不起作用。
我也试过SIGTERM
仍然没有解决我的问题。另外,我认为我的问题有其根源,因为我的 bash 脚本专门捕获 SIGINT
,但在从服务器获取信号时似乎没有执行陷阱语句。
你试过p.terminate()
或p.kill()
吗?
尝试将所有进程分组并杀死它。正如这里提到的。 ***.com/questions/4789837/….
如果你想杀死一个进程树然后使用the solution from @AliSAIDOMAR 's comment(如果你不需要优雅地关闭进程;你可以立即发送SIGKILL)
【参考方案1】:
感谢大家的贡献,最终对我有用的是阿里链接的方法。我使用这个附加参数启动了所有子流程:
preexec_fn=os.setpgrp
然后调用
os.killpg(p.pid, signal.SIGTERM)
SIGTERM
、SIGINT
、kill()
或 terminate()
单独不适用于我的 shell 脚本。该脚本在内部启动了两个服务 (sudo service start
),并且应该在陷阱函数中 sudo service stop
它们,但没有按预期工作。
实际上,我在另一个不会关闭的进程上遇到了更多麻烦——一个没有部署但只是作为脚本启动的 Python 服务器。不知道为什么 killpg
方法不适用于此方法。我终于解决了这个问题,让它将它的 pid 写入一个文件,然后让父脚本读出它并 kill
那个 pid。
【讨论】:
以上是关于正确关闭 Python 中的子进程 [重复]的主要内容,如果未能解决你的问题,请参考以下文章