从python中杀死包含其子进程的子进程

afr*_*las 19 python unix subprocess

我正在使用python 2.5上的子进程模块生成一个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)
Run Code Online (Sandbox Code Playgroud)

一旦自动化测试完成,该过程应该被杀死.我正在使用os.kill这个:

os.killpg(selenium_server_process.pid, signal.SIGTERM)
selenium_server_process.wait()
Run Code Online (Sandbox Code Playgroud)

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

如何杀死shell以及由它生成的任何其他进程?

ber*_*rio 29

处理一般问题:

p=subprocess.Popen(your_command, preexec_fn=os.setsid)
os.killpg(os.getpgid(p.pid), signal.SIGTERM)
Run Code Online (Sandbox Code Playgroud)

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


Tho*_*ers 4

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

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)
Run Code Online (Sandbox Code Playgroud)

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

如果您有理由调用 shell(上面的代码没有,并且没有 shell,您无法做一些事情,但假设您这样做),则必须让 shell 向您传递它启动的进程的 pid不知何故。这样做并不简单,而且要视情况而定。

  • 或者,如果您出于任何原因确实涉及 shell(假设您想要扩展/替换/其他),请在开头使用“exec”以避免 shell 分叉。(具体来说,只需在“命令”定义的开头添加“exec”即可解决您的问题。) (2认同)
  • 不过,您真的有涉及 shell 的“理由”吗?很少有。 (2认同)