简体   繁体   English

Python:使用subprocess.Popen执行长时间运行的进程,将其杀死,并访问其输出

[英]Python: executing a long-running process with subprocess.Popen, killing it, and accessing to its output

I'm trying to run a "long-running" process as root (because I have to), in a thread, in python, then kill it, and then access to its output. 我试图以root身份(因为必须这样做)在线程中,python中运行“长时间运行”的进程,然后将其杀死,然后访问其输出。

The process in question is "babeld", and when I just launch it in a terminal, it outputs text on stdout. 有问题的过程是“生成”,当我在终端中启动它时,它会在stdout上输出文本。 Yet, when I run the following code, I do not have any access to stderr or stdout: 但是,当我运行以下代码时,我无权访问stderr或stdout:

% ./example.py                                                                                                                                                                                                                                                                                   
Waiting for output
Pgid: 13445, pid: 13445
Stopping task
Permission Error!
Calling sudo kill 13445
B
None
None
End

The code: 编码:

#!/usr/bin/env python3

import subprocess
import threading
import time
import os

def main():
    task = TaskManager()
    task.launch()
    time.sleep(2)
    task.stop()

    print(task.stdout)
    print(task.stderr)


class TaskManager(threading.Thread):
    def __init__(self):
        super().__init__()
        self.start_event = threading.Event()
        self.stderr = None
        self.stdout = None
        self.pgid = None
        self.task = None
        self.start()


    def run(self):
        self.start_event.wait()
        self.task = subprocess.Popen(["sudo", "babeld", "-d", "2", "wlp2s0"],
                                     stdout=subprocess.PIPE,
                                     stderr=subprocess.PIPE,
                                     preexec_fn=os.setsid)
        self.pgid = os.getpgid(self.task.pid)
        print("Waiting for output")
        self.stdout, self.stderr = self.task.communicate()
        print("End")

    def launch(self):
        self.start_event.set()

    def stop(self):
        print("Pgid: %s, pid: %s" % (self.pgid, self.task.pid))
        try:
            print("Stopping task")
            self.task.terminate()
        except PermissionError:
            print("Permission Error!")
            print("Calling sudo kill %d" % self.pgid)
            subprocess.check_call(["sudo", "kill", str(self.pgid)])
            print("B")

if __name__ == '__main__':
    main()

How to properly kill processes running as root, while having access to their stderr and stdout? 如何在有权访问其stderr和stdout的同时正确杀死以root身份运行的进程?

Thanks, 谢谢,

The recipe is simple: do not use communicate . 配方很简单:不要使用communicate You may replace your self.stdout and self.stderr class attributes with the following getters: 您可以使用以下getter来替换self.stdoutself.stderr类属性:

@property
def stdout(self):
    return self.task.stdout.read()

@property
def stderr(self):
    return self.task.stderr.read()

BTW, this approach gives you an opportunity to reject threading usage in your code. 顺便说一句,这种方法使您有机会拒绝代码中的线程使用。 Example: 例:

# !/usr/bin/env python3

import subprocess
import time
import os


def main():
    task = TaskManager()
    task.launch()
    time.sleep(2)
    task.stop()

    print(task.stdout)
    print(task.stderr)


class TaskManager:
    def __init__(self):
        self.pgid = None
        self.task = None

    @property
    def stdout(self):
        return self.task.stdout.read()

    @property
    def stderr(self):
        return self.task.stderr.read()

    def launch(self):
        self.task = subprocess.Popen(["sudo", "babeld", "-d", "2", "wlp2s0"],
                                     stdout=subprocess.PIPE,
                                     stderr=subprocess.PIPE,
                                     preexec_fn=os.setsid)
        self.pgid = os.getpgid(self.task.pid)
        print("Waiting for output")

    def stop(self):
        print("Pgid: %s, pid: %s" % (self.pgid, self.task.pid))
        try:
            print("Stopping task")
            self.task.terminate()
        except PermissionError:
            print("Permission Error!")
            print("Calling sudo kill %d" % self.pgid)
            subprocess.check_call(["sudo", "kill", str(self.pgid)])
            print("B")


if __name__ == '__main__':
    main()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM