管道命令输出,但保留错误代码

Sam*_*BOB 12 unix shell sh

在通过另一个成功的命令传送后,如何从unix命令行应用程序中获取正确的返回码?

详细说明,情况如下:

$ tar -cEvhf - -I ${sh_tar_inputlist} | gzip -5 -c > ${sh_tar_file}  --  when only the tar command fails $?=0
$ echo $?
0
Run Code Online (Sandbox Code Playgroud)

而且,我希望看到的是:

$ tar -cEvhf - -I ${sh_tar_inputlist} 2>${sh_tar_error_file} | gzip -5 -c > ${sh_tar_file}
$ echo $?
1
Run Code Online (Sandbox Code Playgroud)

有谁知道如何做到这一点?

Sha*_*hin 10

使用${PIPESTATUS[0]}来获得在管道中第一个命令的退出状态.

有关详细信息,请参阅http://tldp.org/LDP/abs/html/internalvariables.html#PIPESTATUSREF

如果您的shell不支持,请参阅http://cfajohnson.com/shell/cus-faq-2.html了解其他方法$PIPESTATUS.

  • Downvoted,$ PIPESTATUS**在POSIX中不存在**. (3认同)

Sam*_*BOB 4

这是仅使用 POSIX shell 且不使用临时文件的通用解决方案:

从管道开始: foo | 酒吧| 巴兹

exec 4>&1
error_statuses=`((foo || echo "0:$?" >&3) |
        (bar || echo "1:$?" >&3) | 
        (baz || echo "2:$?" >&3)) 3>&1 >&4`
exec 4>&-
Run Code Online (Sandbox Code Playgroud)

$error_statuses 包含任何失败进程的状态代码(按随机顺序),并带有索引来告诉哪个命令发出每个状态。

# if "bar" failed, output its status:
echo $error_statuses | grep '1:' | cut -d: -f2

# test if all commands succeeded:
test -z "$error_statuses"

# test if the last command succeeded:
echo $error_statuses | grep '2:' >/dev/null
Run Code Online (Sandbox Code Playgroud)