从 python 中杀死一个子进程,包括它的子进程

发布于 2024-08-28 20:27:09 字数 1205 浏览 2 评论 0原文

我正在使用 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 生成了另一个进程,而该进程的 pid 对于我的 python 代码来说是未知的。我尝试使用 os.killpg 杀死进程组,但这也会杀死首先运行此代码的 python 进程。由于其他原因,将 shell 设置为 false 从而避免 java 在 shell 环境中运行也是不可能的。

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

I'm using the subprocess module on python 2.5 to spawn a java program (the selenium server, to be precise) as follows:

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)

This process is supposed to get killed once the automated tests are finished. I'm using os.kill to do this:

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

This does not work. The reason is that the shell subprocess spawns another process for java, and the pid of that process is unknown to my python code. I've tried killing the process group with os.killpg, but that kills also the python process which runs this code in the first place. Setting shell to false, thus avoiding java to run inside a shell environment, is also out of the question, due to other reasons.

How can I kill the shell and any other processes generated by it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

惟欲睡 2024-09-04 20:27:09

处理一般问题:

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

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

To handle the general problem:

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

setsid will run the program in a new session, thus assigning a new process group to it and its children. calling os.killpg on it thus won't bring down your own python process also.

萧瑟寒风 2024-09-04 20:27:09

在这种情况下,明显的解决方案是不涉及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不知何故。这样做并不简单,而且要视情况而定。

The obvious solution in this case is to not involve the 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)

This will make the process be the Java process directly. Keep in mind that it may still spawn processes that are not part of the process group, so os.killpg may still not know about killing them.

If you have a reason to invoke the shell (the above code does not, and there are few things you cannot do without the shell, but suppose you do), you would have to make the shell pass you the pid of the process it started somehow. Doing this is not straightforward, and rather situational.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文