捕获从Python调用的程序的“所有”终端输出

发布于 2021-01-29 15:01:19

我有一个程序可以执行为

./install.sh

这将安装一堆东西,并且屏幕上发生了很多活动。

现在,我正在尝试通过执行

p = subprocess.Popen(executable, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()

希望所有发生在屏幕上的活动都被捕获在out(或err)中。但是,在进程运行时,内容直接打印到终端,而不会捕获到out或中err,在进程运行后,它们都为空。

这里会发生什么?如何捕获此内容?

关注者
0
被浏览
49
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    通常,您所做的已经足以将所有输出传递到变量。

    一个例外是,如果您正在运行的程序/dev/tty用于直接连接到其控制终端,并通过该终端而不是通过stdout(FD 1)和stderr(FD
    2)发出输出。通常对安全敏感的IO(例如密码提示)执行此操作,但很少看到。


    为了证明这一点有效,您可以将以下代码完全复制并粘贴到Python shell中:

    import subprocess
    executable = ['/bin/sh', '-c', 'echo stdout; echo stderr >&2']
    p = subprocess.Popen(executable, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out, err = p.communicate()
    print "---"
    print "output: ", out
    print "stderr: ", err
    

    ……相反,为了证明该案例 无效

    import subprocess
    executable = ['/bin/sh', '-c', 'echo uncapturable >/dev/tty']
    p = subprocess.Popen(executable, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out, err = p.communicate()
    print "---"
    print "output: ", out
    

    在这种情况下,内容将直接写入TTY,而不是stdout或stderr。不使用提供伪造TTY的程序(例如scriptexpect)就无法捕获此内容。因此,使用script

    import subprocess
    executable = ['script', '-q', '/dev/null',
                  '/bin/sh', '-c', 'echo uncapturable >/dev/tty']
    p = subprocess.Popen(executable, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out, err = p.communicate()
    print "---"
    print "output: ", out
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看