rou*_*ble 35 bash stdout stderr tee
要将stdout和stderr重定向(并附加)到文件中,同时还在终端上显示它,我这样做:
command 2>&1 | tee -a file.txt
Run Code Online (Sandbox Code Playgroud)
但是,有没有其他方法可以做到这一点,以便我获得退出状态的准确值?
也就是说,如果我测试$?,我想看到退出状态command,而不是退出状态tee.
我知道我可以${PIPESTATUS[0]}在这里使用而不是$?,但我正在寻找另一种不需要检查的解决方案PIPESTATUS.
Mar*_*tin 30
也许您可以将PIPESTATUS的退出值放入 $?
command 2>&1 | tee -a file.txt ; ( exit ${PIPESTATUS} )
Run Code Online (Sandbox Code Playgroud)
有一些bash风味的另一种可能性是打开pipefail选项:
pipefail
如果设置,则管道的返回值是以非零状态退出的最后(最右侧)命令的值,如果管道中的所有命令都成功退出,则返回零.默认情况下禁用此选项.
set -o pipefail
...
command 2>&1 | tee -a file.txt || echo "Command (or tee?) failed with status $?"
Run Code Online (Sandbox Code Playgroud)
这已经说过了,PIPESTATUS可移植地实现功能的唯一方法(例如它也适用于POSIX sh)有点复杂,即需要临时文件将管道退出状态传播回父shell进程:
{ command 2>&1 ; echo $? >"/tmp/~pipestatus.$$" ; } | tee -a file.txt
if [ "`cat \"/tmp/~pipestatus.$$\"`" -ne 0 ] ; then
...
fi
Run Code Online (Sandbox Code Playgroud)
或者,封装以便重复使用:
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 $?"
Run Code Online (Sandbox Code Playgroud)
或者,更一般地说:
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
Run Code Online (Sandbox Code Playgroud)