在杀死用python子进程Popen启动的进程时,如何关闭stdout-pipe?

ice*_*eam 9 python subprocess stdout kill pipe

我想知道在杀死在不同线程中启动的子进程时是否可以关闭通信管道.如果我不调用communic(),那么kill()将按预期工作,在一秒钟而不是五秒后终止进程.

我在这里找到了一个类似问题的讨论,但我没有得到真正的答案.我假设我要么必须能够关闭管道,要么明确地杀死子子进程(在示例中为"sleep")并杀死它以取消阻塞管道.

我也试着在SO上找到她的答案,但是我只发现了这个以及这个,而且这个并没有直接解决这个问题,据我所知(?).

所以我想要做的是能够在第二个线程中运行命令并获取其所有输出,但是当我愿意时能够立即杀死它.我可以通过一个文件和尾巴那个或类似的,但我认为应该有一个更好的方法来做到这一点?

import subprocess, time
from threading import Thread

process = None

def executeCommand(command, runCommand):
    Thread(target=runCommand, args=(command,)).start()

def runCommand(command):
    global process
    args = command.strip().split()
    process = subprocess.Popen(args, shell=False, stdout=subprocess.PIPE)

    for line in process.communicate():
        if line:
            print "process:", line,

if __name__ == '__main__':
    executeCommand("./ascript.sh", runCommand)
    time.sleep(1)
    process.kill()
Run Code Online (Sandbox Code Playgroud)

这是脚本:

#!/bin/bash
echo "sleeping five"
sleep 5
echo "slept five"
Run Code Online (Sandbox Code Playgroud)

产量

$ time python poc.py 
process: sleeping five

real    0m5.053s
user    0m0.044s
sys 0m0.000s
Run Code Online (Sandbox Code Playgroud)

ric*_*rdw 6

我认为问题是process.kill()只杀死直接子进程(bash),而不是bash脚本的子进程.

这里描述了问题和解决方案:

使用Popen(...,preexec_fn = os.setsid)创建进程组,并使用os.pgkill来终止整个进程组.例如

import os
import signal
import subprocess
import time
from threading import Thread

process = None

def executeCommand(command, runCommand):
    Thread(target=runCommand, args=(command,)).start()

def runCommand(command):
    global process
    args = command.strip().split()
    process = subprocess.Popen(
        args, shell=False, stdout=subprocess.PIPE, preexec_fn=os.setsid)

    for line in process.communicate():
        if line:
            print "process:", line,

if __name__ == '__main__':
    executeCommand("./ascript.sh", runCommand)
    time.sleep(1)
    os.killpg(process.pid, signal.SIGKILL)
Run Code Online (Sandbox Code Playgroud)
$ time python poc.py 
process: sleeping five

real    0m1.051s
user    0m0.032s
sys 0m0.020s
Run Code Online (Sandbox Code Playgroud)