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

时间:2010-04-14 15:51:42

标签: 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)

一旦自动化测试完成,这个过程就会被杀死。我正在使用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及其生成的任何其他进程?

2 个答案:

答案 0 :(得分:27)

处理一般问题:

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

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

答案 1 :(得分: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)

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

如果你有理由调用shell(上面的代码没有,并且没有shell你可以做的事情很少,但假设你这样做),你必须让shell传递给你的pid。过程以某种方式开始。这样做并不简单,而是情境化。