Подтвердить что ты не робот

Убийство подпроцесса, включая его дочерние элементы из python

Я использую модуль подпроцесса на python 2.5, чтобы создать java-программу (точнее, селеновый сервер) следующим образом:

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()

Это не работает. Причина в том, что подпроцесс оболочки порождает другой процесс для java, а pid этого процесса неизвестен моему коду python. Я попытался убить группу процессов с помощью os.killpg, но это также убивает процесс python, который запускает этот код в первую очередь. Установка оболочки на false, что позволяет избежать java для запуска внутри оболочки, также не может быть и речи по другим причинам.

Как я могу убить оболочку и любые другие процессы, созданные ею?

4b9b3361

Ответ 1

Чтобы справиться с общей проблемой:

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

setsid запускает программу в новом сеансе, тем самым присваивая ей новую группу процессов и ее дочерние элементы. вызов os.killpg на нем, таким образом, также не приведет к снижению вашего собственного процесса python.

Ответ 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 может все еще не знать об их уничтожении.

Если у вас есть причина для вызова оболочки (приведенного выше кода нет, и есть несколько вещей, которые вы не можете обойти без оболочки, но предположите, что вы это делаете), вам нужно заставить оболочку передать вам pid процесс начал как-то. Делать это не просто, а скорее ситуативно.