如何终止用shell = True启动的pythonsubprocess
我使用以下命令启动subprocess:
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
但是,当我试图杀死使用:
p.terminate()
要么
p.kill()
该命令一直在后台运行,所以我想知道如何才能真正终止进程。
请注意,当我运行命令:
p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)
发出p.terminate()
时,它终止成功。
使用一个进程组 ,以便能够向组中的所有进程发送一个信号。 为此,您应该将会话ID附加到衍生/subprocess的父进程,这是您的情况下的shell。 这将使其成为stream程的组长。 所以现在,当一个信号被发送到进程组领导,它被传送到这个组的所有subprocess。
代码如下:
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
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) p.kill()
p.kill()
最终杀死了shell进程, cmd
仍在运行。
我发现一个方便的解决方法是:
p = subprocess.Popen("exec " + cmd, stdout=subprocess.PIPE, shell=True)
这将导致cmdinheritanceshell进程,而不是让shell启动一个subprocess,这个subprocess不会被终止。 p.pid
将是你的cmd进程的id。
p.kill()
应该工作。
我不知道这对你的pipe道有什么影响。
如果你可以使用psutil ,那么这是完美的作品:
import subprocess import psutil def kill(proc_pid): process = psutil.Process(proc_pid) for proc in process.children(recursive=True): proc.kill() process.kill() proc = subprocess.Popen(["infinite_app", "param"], shell=True) try: proc.wait(timeout=3) except subprocess.TimeoutExpired: kill(proc.pid)
我可以使用它
from subprocess import Popen process = Popen(command, shell=True) Popen("TASKKILL /F /PID {pid} /T".format(pid=process.pid))
它杀死了我给的命令cmd.exe
和程序。
(在Windows上)
正如Sai所说,shell是小孩,所以信号被截获 – 我发现的最好的方法是使用shell = False并使用shlex来分割命令行:
if isinstance(command, unicode): cmd = command.encode('utf8') args = shlex.split(cmd) p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
然后p.kill()和p.terminate()应该如何工作。
当shell=True
,shell是subprocess,命令是subprocess。 所以任何SIGTERM
或者SIGKILL
都会杀死shell而不是它的subprocess,我不记得有一个好办法。 我能想到的最好的方法是使用shell=False
,否则当你杀死父shell进程时,它会留下一个不存在的shell进程。