【问题标题】:Killing a subprocess including its children from python [duplicate]从python中杀死一个子进程,包括它的子进程[重复]
【发布时间】:2011-02-07 23:54:04
【问题描述】:

我正在使用 python 2.5 上的 subprocess 模块来生成一个 java 程序(准确地说是 selenium 服务器),如下所示:

import os
import subprocess

display = 0
log_file_path = "/tmp/selenium_log.txt"
selenium_port = 4455
selenium_folder_path = "/wherever/selenium/lies"

env = os.environ
env["DISPLAY"] = ":%d.0" % display
command = ["java", 
           "-server",
           "-jar", 
           'selenium-server.jar',
           "-port %d" % selenium_port]
log = open(log_file_path, 'a')
comm = ' '.join(command)
selenium_server_process = subprocess.Popen(comm,
                                           cwd=selenium_folder_path,
                                           stdout=log,
                                           stderr=log,
                                           env=env,
                                           shell=True)

一旦自动化测试完成,这个进程应该被终止。我正在使用os.kill 来执行此操作:

os.killpg(selenium_server_process.pid, signal.SIGTERM)
selenium_server_process.wait()

这不起作用。原因是 shell 子进程为 java 生成了另一个进程,而我的 python 代码不知道该进程的 pid。我尝试使用os.killpg 杀死进程组,但这也杀死了首先运行此代码的python 进程。由于其他原因,将 shell 设置为 false,从而避免 java 在 shell 环境中运行,也是不可能的。

如何杀死 shell 和它生成的任何其他进程?

【问题讨论】:

标签: python unix subprocess


【解决方案1】:

处理一般问题:

p=subprocess.Popen(your_command, preexec_fn=os.setsid)
os.killpg(os.getpgid(p.pid), signal.SIGTERM)

setsid 将在新会话中运行程序,从而为它及其子进程分配一个新进程组。因此调用os.killpg 也不会关闭你自己的python 进程。

【讨论】:

  • 不用setsid;你可以call os.setsid in Python
  • 不,你不能......这将改变进程本身的会话,如果你所追求的只是杀死孩子,那不是你想要的
  • 重读问题的标题:"Killing a subprocess including its children from python"
  • fyi,preexec_fn 在 fork 之后执行(在子进程中)
  • 标题说“子进程”+子进程,我说“子进程”(意思是子进程+子进程),你说“调用进程本身+子进程(子进程及其子进程)”
【解决方案2】:

在这种情况下,显而易见的解决方案是不涉及外壳

import os
import subprocess

display = 0
log_file_path = "/tmp/selenium_log.txt"
selenium_port = 4455
selenium_folder_path = "/wherever/selenium/lies"

env = os.environ
env["DISPLAY"] = ":%d.0" % display
command = ["java", 
           "-server",
           "-jar", 
           'selenium-server.jar',
           "-port",
           str(selenium_port)]
log = open(log_file_path, 'a')
selenium_server_process = subprocess.Popen(command,
                                           cwd=selenium_folder_path,
                                           stdout=log,
                                           stderr=subprocess.STDOUT,
                                           env=env)

这将使进程直接成为Java进程。请记住,它可能仍会生成不属于进程组的进程,因此 os.killpg 可能仍然不知道要杀死它们。

如果你有理由调用 shell(上面的代码没有,没有 shell 你不能做一些事情,但假设你这样做了),你必须让 shell 传递你的 pid过程它以某种方式开始。这样做并不简单,而是视情况而定。

【讨论】:

  • 或者,如果您出于任何原因确实涉及 shell(假设您想要扩展/替换/其他),请在开头使用“exec”以避免 shell 分叉。 (具体来说,只需在“command”定义的开头添加“exec”就可以解决您的问题。)
  • @moshez,太棒了!做到了。非常感谢。
  • 你真的有 原因 让 shell 参与进来吗?很少有。
猜你喜欢
  • 2010-12-08
  • 2016-03-23
  • 1970-01-01
  • 1970-01-01
  • 2011-09-26
  • 2017-08-05
  • 2013-10-27
  • 1970-01-01
  • 2019-11-08
相关资源
最近更新 更多