正确关闭 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)

SIGTERMSIGINTkill()terminate() 单独不适用于我的 shell 脚本。该脚本在内部启动了两个服务 (sudo service start),并且应该在陷阱函数中 sudo service stop 它们,但没有按预期工作。

实际上,我在另一个不会关闭的进程上遇到了更多麻烦——一个没有部署但只是作为脚本启动的 Python 服务器。不知道为什么 killpg 方法不适用于此方法。我终于解决了这个问题,让它将它的 pid 写入一个文件,然后让父脚本读出它并 kill 那个 pid。

【讨论】:

以上是关于正确关闭 Python 中的子进程 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

Python中的子进程执行两个任务? [关闭]

从python中杀死一个子进程,包括它的子进程[重复]

带有管道的子进程调用[重复]

如何在 Python 中终止我的子进程 [重复]

如何在其他网络命名空间中的子进程与父进程之间正确通信?

Perl:关闭信号处理程序中的子进程管道挂起?