如何终止使用 shell=True 启动的 python 子进程

新手上路,请多包涵

我正在使用以下命令启动一个子进程:

 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)

但是,当我尝试使用以下方法杀死时:

 p.terminate()

或者

p.kill()

该命令一直在后台运行,所以我想知道如何才能真正终止该进程。

请注意,当我使用以下命令运行命令时:

 p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)

发出 p.terminate() 时,它确实成功终止。

原文由 user175259 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 406
2 个回答

使用 进程组 以便能够向组中的所有进程发送信号。为此,您应该将会话 ID 附加到衍生/子进程的父进程,在您的情况下这是一个外壳。这将使其成为流程的组长。所以现在,当一个信号被发送到进程组组长时,它会被传输到这个组的所有子进程。

这是代码:

 import os
import signal
import subprocess

# The os.setsid() is passed in the argument preexec_fn so
# it's run after the fork() and before  exec() to run the shell.
pro = subprocess.Popen(cmd, stdout=subprocess.PIPE,
                       shell=True, preexec_fn=os.setsid)

os.killpg(os.getpgid(pro.pid), signal.SIGTERM)  # Send the signal to all the process groups

原文由 mouad 发布,翻译遵循 CC BY-SA 3.0 许可协议

p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
p.kill()

p.kill() 最终终止了 shell 进程并且 cmd 仍在运行。

我找到了一个方便的解决方法:

 p = subprocess.Popen("exec " + cmd, stdout=subprocess.PIPE, shell=True)

这将导致 cmd 继承 shell 进程,而不是让 shell 启动一个不会被杀死的子进程。 p.pid 将是你的 cmd 进程的 ID。

p.kill() 应该可以工作。

我不知道这会对你的管道产生什么影响。

原文由 Bryant Hansen 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题