【问题标题】:Pipe command output, but keep the error code [duplicate]管道命令输出,但保留错误代码[重复]
【发布时间】:2012-02-08 15:25:27
【问题描述】:

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

具体情况如下:

$ tar -cEvhf - -I ${sh_tar_inputlist} | gzip -5 -c > ${sh_tar_file}  --  when only the tar command fails $?=0
$ echo $?
0

而且,我想看到的是:

$ tar -cEvhf - -I ${sh_tar_inputlist} 2>${sh_tar_error_file} | gzip -5 -c > ${sh_tar_file}
$ echo $?
1

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

【问题讨论】:

  • $? 保存错误代码。您可以将其保存在变量中。
  • 我需要保存中间命令的返回码,而不是最后一个命令。

标签: shell unix sh


【解决方案1】:

使用${PIPESTATUS[0]} 获取管道中第一个命令的退出状态。

详情见http://tldp.org/LDP/abs/html/internalvariables.html#PIPESTATUSREF

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

【讨论】:

  • 否决,$PIPESTATUS 在 POSIX 中不存在
【解决方案2】:

查看$PIPESTATUS,它是一个保存退出状态的数组变量。所以${PIPESTATUS[0]} 保存管道中第一个命令的退出状态,${PIPESTATUS[1]} 保存第二个命令的退出状态,以此类推。

例如:

$ tar -cEvhf - -I ${sh_tar_inputlist} | gzip -5 -c > ${sh_tar_file}
$ echo ${PIPESTATUS[0]}

要打印出所有状态,请使用:

$ echo ${PIPESTATUS[@]}

【讨论】:

  • 谢谢,但我的脚本不使用 bash。我使用 #!/bin/sh
  • @dogbane,${PIPESTATUS[*]}${PIPESTATUS[@]} 之间有什么区别吗?我总是用前者...
  • 否决,$PIPESTATUS 在 POSIX 中不存在
  • 对于 zsh,${pipestatus[1]} 似乎是第一个命令的代码。
【解决方案3】:

这是一个仅使用 POSIX shell 而没有临时文件的通用解决方案:

从管道开始: 富 |酒吧 |呵呵

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

$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

【讨论】:

    【解决方案4】:

    正如其他人指出的那样,一些现代 shell 提供 PIPESTATUS 来获取此信息。在classic sh中,有点难度,需要用到fifo:

    #!/bin/sh 陷阱 'rm -rf $TMPDIR' 0 TMPDIR=$( mktemp -d ) mkfifo ${FIFO=$TMPDIR/fifo} cmd1 > $FIFO & cmd2

    (好吧,你不需要使用先进先出。你可以让管道中的命令回显一个状态变量并在主shell中对其进行评估,将文件描述符重定向到整个地方,并且基本上向后弯曲到检查东西,但使用先进先出要容易得多。)

    【讨论】:

    • 你好,我已经尝试过这种技术,但它没有接缝工作:我测试过:/usr/bin/tar -cMEvhf - -I /tmp/test.tmp > $FIFO & gzip -5 -c /tmp/test.bkz 等待 $! echo cmd1的返回值为$?
    • 即使 cmd1 失败,$?=0
    猜你喜欢
    • 2011-10-15
    • 1970-01-01
    • 2021-05-20
    • 2011-06-25
    • 2011-11-30
    • 1970-01-01
    • 2015-11-05
    • 2012-10-17
    • 2017-01-07
    相关资源
    最近更新 更多