如何使用python subprocess.call,将stdout的副本发送到日志文件,同时检测第一个命令的结果

如何使用python subprocess.call,将stdout的副本发送到日志文件,同时检测第一个命令的结果,python,bash,subprocess,Python,Bash,Subprocess,我的python脚本需要调用一个程序,检测它是否失败(例如,result!=0),并将程序的输出发送到两个标准输出和一个日志文件 我的默认shell是bash。我正在使用Python 2.7.9 要将输出同时发送到标准输出和文件,我通常使用tee: result = subprocess.call('some_program --an-option | tee -a ' + logfile , shell=True) 但是,即使第一个命令失败,bash中的管道也将返回true,因此这种方法无

我的python脚本需要调用一个程序,检测它是否失败(例如,
result!=0
),并将程序的输出发送到两个标准输出和一个日志文件

我的默认shell是bash。我正在使用Python 2.7.9

要将输出同时发送到标准输出和文件,我通常使用
tee

result = subprocess.call('some_program --an-option  | tee -a ' + logfile , shell=True)
但是,即使第一个命令失败,bash中的管道也将返回true,因此这种方法无法检测命令是否失败

如果我尝试在命令中使用
set-o pipefail
(以便结果将指示第一个命令是否失败),如下所示:

result = subprocess.call('set -o pipefail && some_program --an_option  | tee -a ' + logfile , shell=True)
我得到错误
/bin/sh:1:set:invalical选项-o pipefail

python中是否有方法调用命令,将输出发送到普通stdout控制台和日志文件,并仍然检测命令是否失败


注意:我们必须继续将一些_程序的输出发送到stdout,因为stdout正在发送到websocket

我倾向于将stdout发送到管道,然后在Python代码中读取管道。Python代码可以根据需要写入标准输出、文件等。它还允许您设置shell=False,因为将其设置为True是一个潜在的安全问题,如文档中所述

但是,bash中的管道将返回true,即使第一个命令 失败,因此此方法无法检测命令是否失败

那不是真的。
但我想你的意思是:
“some_”程序——选项| tee-a'+logfile
退出状态代码始终为0,即使在任何命令部分失败

嗯,使用多个命令(当使用
&&
| |
时)或通过管道将多个命令连接在一起会导致返回不可靠的退出状态代码

无论如何,在命令中:
some_程序——如果某个_程序失败,则不会写入选项| tee-a'+logfile
logfile。所以你不必担心退出密码

无论如何,与子流程一起执行管道的最佳方法是创建对象并处理
stdout
stdin

将子进程作为sp导入

STATUS_OK = 0
logfile = '/tmp/test.log'
commands = {
    'main' :   'ls /home',
    'pipe_to': 'tee -a ' + logfile
}

process = sp.Popen(commands['main'], shell=True, stdout=sp.PIPE)
# explicitly force waits till command terminate, set and return exit status code
process.wait()

if process.returncode == STATUS_OK:
    stdoutdata = process.communicate()[0]
    # pipe last command output to "tee" command
    sp.Popen(commands['pipe_to'], stdin=sp.PIPE, shell=1).communicate(stdoutdata)
else:
    # do something when command fails 'ls /hom' (in this case) fails
    pass
就是这样
I调用的最后一个Popen将
ls
命令的最后一个输出发送到
tee
命令STDIN

在Python文档中有一个小教程,叫做,也许你想看看

我得到了错误/bin/sh:1:set:invalize选项-o pipefail

传递
executable='/bin/bash'
否则使用
/bin/sh

您可以在纯Python中实现
tee

#!/usr/bin/env python2
import sys
from subprocess import Popen, PIPE

chunk_size = 1 << 13    
p = Popen(["some_program", "--an-option"], stdout=PIPE, bufsize=1)
with p.stdout, open('logfile', 'ab') as logfile:
    for chunk in iter(lambda: p.stdout.read(chunk_size), b''):
        sys.stdout.write(chunk)
        logfile.write(chunk)
if p.wait() != 0:
    raise Error
#/usr/bin/env蟒蛇2
导入系统
从子流程导入Popen、PIPE
块大小=1