杀死以python子进程Popen开始的进程时,如何关闭stdout-pipe? [英] How do I close the stdout-pipe when killing a process started with python subprocess Popen?

查看:425
本文介绍了杀死以python子进程Popen开始的进程时,如何关闭stdout-pipe?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道杀死另一个线程中启动的子进程时是否有可能关闭通信管道.如果我不打电话给communication(),那么kill()将按预期工作,在一秒而不是五秒后终止进程.

I wonder if it is possible to shut down the communication pipe when killing a subprocess started in a different thread. If I do not call communicate() then kill() will work as expected, terminating the process after one second instead of five.

我在此处上找到了类似问题的讨论,但没有得到真正的答案.我假设我要么必须能够关闭管道,要么必须明确杀死子子进程(在示例中为"sleep"),然后杀死该子子进程才能解除阻塞管道.

I found a discussion of a similar problem here, but I got no real answers. I assume that I either have to be able to close the pipe or to explicitly kill the sub-subprocess (which is "sleep" in the example) and kill that to unblock the pipe.

我也尝试在SO上找到答案,但我只找到了

I also tried to find the answer her on SO, but I only found this and this and this, which do not directly address this problem as far as I can tell (?).

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

So the thing I want to do is to be able to run a command in a second thread and get all its output, but be able to kill it instantly when I so desire. I could go via a file and tail that or similar, but I think there should be a better way to do this?

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()

这是脚本:

#!/bin/bash
echo "sleeping five"
sleep 5
echo "slept five"

输出

$ time python poc.py 
process: sleeping five

real    0m5.053s
user    0m0.044s
sys 0m0.000s

推荐答案

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

I think the problem is that process.kill() only kills the immediate child process (bash), not the sub-processes of the bash script.

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

The problem and solution are described here:

  • http://www.doughellmann.com/PyMOTW/subprocess/#process-groups-sessions
  • How to terminate a python subprocess launched with shell=True

使用Popen(...,preexec_fn = os.setsid)创建一个进程组,并使用os.pgkill杀死整个进程组.例如

Use Popen(..., preexec_fn=os.setsid) to create a process group and os.pgkill to kill the entire process group. eg

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)


$ time python poc.py 
process: sleeping five

real    0m1.051s
user    0m0.032s
sys 0m0.020s

这篇关于杀死以python子进程Popen开始的进程时,如何关闭stdout-pipe?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆