如何杀死一个由subprocess.check_output()创build的父子死亡的Pythonsubprocess?

我正在Linux机器上运行一个python脚本,它使用subprocess.check_output()创build一个subprocess,如下所示:

subprocess.check_output(["ls", "-l"], stderr=subprocess.STDOUT) 

问题是,即使父进程死亡,孩子仍然在运行。 父母死后有没有办法杀死孩子的过程?

Solutions Collecting From Web of "如何杀死一个由subprocess.check_output()创build的父子死亡的Pythonsubprocess?"

你的问题是使用subprocess.check_output – 你是正确的,你不能得到使用该接口的子PID。 改用Popen:

 proc = subprocess.Popen(["ls", "-l"], stdout=PIPE, stderr=PIPE) # Here you can get the PID global child_pid child_pid = proc.pid # Now we can wait for the child to complete (output, error) = proc.communicate() if error: print "error:", error print "output:", output 

为了确保你在出口处杀死了孩子:

 import os import signal def kill_child(): if child_pid is None: pass else: os.kill(child_pid, signal.SIGTERM) import atexit atexit.register(kill_child) 

是的,你可以通过两种方法来实现。 他们都需要你使用check_output而不是check_output 。 首先是一个更简单的方法,使用try..finally,如下所示:

 from contextlib import contextmanager @contextmanager def run_and_terminate_process(*args, **kwargs): try: p = subprocess.Popen(*args, **kwargs) yield p finally: p.terminate() # send sigterm, or ... p.kill() # send sigkill def main(): with run_and_terminate_process(args) as running_proc: # Your code here, such as running_proc.stdout.readline() 

这将捕获sigint(键盘中断)和sigterm,但不是sigkill(如果你杀死你的脚本-9)。

另一种方法有点复杂,并使用ctypes的prctl PR_SET_PDEATHSIG。 一旦家长出于任何原因(甚至是sigkill)退出,系统会向孩子发送信号。

 import signal import ctypes libc = ctypes.CDLL("libc.so.6") def set_pdeathsig(sig = signal.SIGTERM): def callable(): return libc.prctl(1, sig) return callable p = subprocess.Popen(args, preexec_fn = set_pdeathsig(signal.SIGTERM)) 

不知道细节,但最好的方法仍然是用信号捕捉错误(甚至可能是所有的错误),并终止那里的任何剩余进程。

 import signal import sys import subprocess import os def signal_handler(signal, frame): sys.exit(0) signal.signal(signal.SIGINT, signal_handler) a = subprocess.check_output(["ls", "-l"], stderr=subprocess.STDOUT) while 1: pass # Press Ctrl-C (breaks the application and is catched by signal_handler() 

这只是一个模型,你需要抓住更多的信号,但这个想法可能会让你开始,你还需要检查产生的进程。

http://docs.python.org/2/library/os.html#os.kill http://docs.python.org/2/library/subprocess.html#subprocess.Popen.pid http:// docs。 python.org/2/library/subprocess.html#subprocess.Popen.kill

我建议重写check_output的个性化版本的原因,因为我刚刚意识到check_output只是为了简单的调试等,因为你不能在执行过程中与它交互太多。

重写check_output:

 from subprocess import Popen, PIPE, STDOUT from time import sleep, time def checkOutput(cmd): a = Popen('ls -l', shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT) print(a.pid) start = time() while a.poll() == None or time()-start <= 30: #30 sec grace period sleep(0.25) if a.poll() == None: print('Still running, killing') a.kill() else: print('exit code:',a.poll()) output = a.stdout.read() a.stdout.close() a.stdin.close() return output 

做任何你喜欢的事情,也许把正在执行的程序存储在一个临时变量中,并在退出时用信号或其他方式来阻止主循环的错误/关闭。

最后,为了安全地杀死任何孩子,你仍然需要在主应用程序中捕捉终端,最好的方法是try & except或者signal

手动你可以这样做:

ps aux | grep <process name>

得到PID(第二列)和

kill -9 <PID> -9是强制杀死它