如何终止用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进程。