How to terminate a python subprocess launched with shell=True
Как завершить подпроцесс python, запущенный с помощью shell = True
Я запускаю подпроцесс с помощью следующей команды:
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
Однако, когда я пытаюсь завершить работу с помощью:
p.terminate()
или
p.kill()
Команда продолжает выполняться в фоновом режиме, поэтому мне было интересно, как я могу на самом деле завершить процесс.
Обратите внимание, что когда я запускаю команду с:
p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)
Он успешно завершается при выдаче p.terminate().
Переведено автоматически
Ответ 1
Используйте группу процессов, чтобы включить отправку сигнала всем процессам в группах. Для этого вы должны прикрепить идентификатор сеанса к родительскому процессу порожденных / дочерних процессов, который в вашем случае является оболочкой. Это сделает его лидером группы процессов. Итак, теперь, когда сигнал отправляется лидеру группы процессов, он передается всем дочерним процессам этой группы.
Вот код:
import os import signal import subprocess
# The os.setsid() is passed in the argument preexec_fn so # it's run after the fork() and before exec() to run the shell. pro = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True, preexec_fn=os.setsid)
os.killpg(os.getpgid(pro.pid), signal.SIGTERM) # Send the signal to all the process groups
Ответ 2
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) p.kill()
p.kill() завершает работу процесс оболочки и cmd все еще выполняется.
Я нашел удобное исправление с помощью:
p = subprocess.Popen("exec " + cmd, stdout=subprocess.PIPE, shell=True)
Это приведет к тому, что cmd унаследует процесс оболочки, вместо того, чтобы заставить оболочку запустить дочерний процесс, который не будет уничтожен. p.pid тогда это будет идентификатор вашего процесса cmd.
p.kill() должно сработать.
Однако я не знаю, какой эффект это окажет на ваш канал.
Ответ 3
Если вы можете использовать psutil, то это работает отлично:
import subprocess
import psutil
defkill(proc_pid): process = psutil.Process(proc_pid) for proc in process.children(recursive=True): proc.kill() process.kill()