使用子进程获取多个相互依赖的命令的输出和返回代码

时间:2016-11-17 13:25:15

标签: python subprocess

import subprocess
with open ("log.txt",'a') as log:
    output = subprocess.Popen("ech ;echo hello", shell=True, stdout=log, stderr=subprocess.STDOUT)
    print output.wait() # prints  0

ech将“/ bin / sh:ech:command not found”写入“log.txt”。但返回码为0(SUCCESS),因为最后一个命令成功。我想得到单独的命令返回码而不是最后一个命令的返回码。

另外,假设命令是依赖的 - 例如:cd .. ; pwd - 它们不应拆分并作为两个子流程调用运行,因为pwd不会考虑cd ..的影响

上面的示例仅用于说明目的。请不要建议使用cwd解决此问题。

4 个答案:

答案 0 :(得分:1)

你需要做我总是建议人们做的事情,作为任何Bash脚本的第一行:

set -e (quite standard)
set -o pipefail (requires Bash 3 or later)

然后,只要命令(或管道的一部分)失败,整个脚本就会失败。这样可以在找不到ech后立即停止。

答案 1 :(得分:0)

这看起来更像是一个bash问题。如果您使用错误的命令作为" ech"然后你继续使用其他东西,而不是子进程不知道。

您可以轻松完成的工作是将您的bash命令连接到&&如果所有命令都得到正确执行,这将导致0。

Subprocess本身正在创建一个不同的进程,无论你介绍什么,你都会在那里执行,所以按照建议做的只会在好的情况下导致0。

答案 2 :(得分:0)

你不能简单地做到。如果使用单个命令shell来处理所有命令,则只能获得连接的输出和shell本身的返回值,这将是上次执行的命令的返回值。

另一方面,如果您使用每个命令的专用子进程,则必须模拟真实的shell并专门处理可能会改变环境的每个命令,如cdexport或变量赋值允许依赖应用于以下命令

TL / DR:如果你想模仿一个真正的shell,你将不得不写一个真正的shell ......

答案 3 :(得分:0)

我认为subprocess不能做你想要的。 但是对于你的问题,你可以使用`echo $?'获得退出代码。

cmds = ['ech;', 'echo heelo']
cmds_str = ' echo $?;'.join(cmds) # output 'ech echo $?;echo heelo'

with open ("log.txt",'a') as log:
    output = subprocess.Popen(cmds_str, shell=True, stdout=log, stderr=subprocess.STDOUT)
    print output.wait()

您的文件将是:

/bin/sh: ech: command not found
127
heelo

在这个例子中,最后一个命令的retcode是0。