bash:将stdout和stderrredirect(并追加)到文件和terminal,并获得正确的退出状态

为了将stdout和stderrredirect(并追加)到一个文件,同时也在terminal上显示它,我这样做:

command 2>&1 | tee -a file.txt 

但是,有没有另外一种方法来获得退出状态的准确值?

也就是说,如果我testing$? ,我想看看command的退出状态,而不是退出状态。

我知道我可以使用${PIPESTATUS[0]}而不是$? ,但我正在寻找另一个不涉及检查PIPESTATUS解决scheme。

也许你可以把PIPESTATUS的退出值放到$?

 command 2>&1 | tee -a file.txt ; ( exit ${PIPESTATUS} ) 

另一种可能性,有一些bash风格,打开pipefail选项:

pipefail

如果设置,pipe道的返回值是以非零状态退出的最后一个(最右边的)命令的值,如果pipe道中的所有命令都成功退出,则为零。 该选项默认是禁用的。

 set -o pipefail ... command 2>&1 | tee -a file.txt || echo "Command (or tee?) failed with status $?" 

PIPESTATUS ,实现PIPESTATUSfunction的唯一方法是可移植的(例如,它也适用于POSIX sh )有点复杂,即它需要一个临时文件来将pipe道退出状态传播回父shell进程:

 { command 2>&1 ; echo $? >"/tmp/~pipestatus.$$" ; } | tee -a file.txt if [ "`cat \"/tmp/~pipestatus.$$\"`" -ne 0 ] ; then ... fi 

或者封装以供重用:

 log2file() { LOGFILE="$1" ; shift { "$@" 2>&1 ; echo $? >"/tmp/~pipestatus.$$" ; } | tee -a "$LOGFILE" MYPIPESTATUS="`cat \"/tmp/~pipestatus.$$\"`" rm -f "/tmp/~pipestatus.$$" return $MYPIPESTATUS } log2file file.txt command param1 "param 2" || echo "Command failed with status $?" 

或者更一般地说:

 save_pipe_status() { STATUS_ID="$1" ; shift "$@" echo $? >"/tmp/~pipestatus.$$.$STATUS_ID" } get_pipe_status() { STATUS_ID="$1" ; shift return `cat "/tmp/~pipestatus.$$.$STATUS_ID"` } save_pipe_status my_command_id ./command param1 "param 2" | tee -a file.txt get_pipe_status my_command_id || echo "Command failed with status $?" ... rm -f "/tmp/~pipestatus.$$."* # do this in a trap handler, too, to be really clean 

使用stream程replace:

 command > >( tee -a "$logfile" ) 2>&1 

发球区域运行在一个子shell所以$? 保持命令的退出状态。

有这样一个神秘的POSIX方式:

 exec 4>&1; R=$({ { command1; echo $? >&3 ; } | { command2 >&4; } } 3>&1); exec 4>&- 

它将variablesR设置为command1的返回值,将command1输出设置为command2 ,其输出被redirect到父shell的输出。