【问题标题】:Get exit codes of a pipe when output is assigned to variable (Command Substitution) [duplicate]将输出分配给变量时获取管道的退出代码(命令替换)[重复]
【发布时间】:2017-06-02 15:59:09
【问题描述】:

获取管道命令的退出代码工作正常。

echo "ABC" | false | true
echo ${PIPESTATUS[0]} ${PIPESTATUS[1]} ${PIPESTATUS[2]}
#Output is 0 1 0

但是当我将输出分配给一个变量时,a 无法获得退出代码。

TEST=$(echo "ABC" | false | true)
echo ${PIPESTATUS[0]} ${PIPESTATUS[1]} ${PIPESTATUS[2]}
#Output is 0

如何获取管道进程的退出代码?

【问题讨论】:

  • 我建议不要在命令替换中运行管道。但是,有很多方法可以重写它,这取决于管道的后续阶段是否需要在早期阶段失败时运行。

标签: bash shell pipe


【解决方案1】:

Bash command substitution 发生在子外壳中,因此这些值存在但仅在该子外壳内。您会看到 ${PIPESTATUS[0]} 反映了分配中的 $?(如果您以 | false 结束替换,它将是 1)。

我已更改您的示例以实际包含一些输出。这也适用于原始代码。

# without command substitution
echo "ABC" | false | echo "DEF"
echo "${PIPESTATUS[*]}"

echo "---"

# within command substitution
TEST="$( echo "ABC" | false | echo "DEF"; printf :%s "${PIPESTATUS[*]}" )"
declare -a PIPESTATUS2=( ${TEST##*:} )  # make array w/ content after final colon
if [[ -n "${TEST%:*}" ]]; then          # if there was original output
  TEST="${TEST%:*}"                     # remove trailing results from $TEST
  TEST="${TEST%$'\n'}"                  # remove trailing \n like plain $(…)
else
  TEST=""                               # no original output -> empty string
fi

echo "$TEST"
echo "${PIPESTATUS2[*]}"

输出:

DEF
141 1 0
---
DEF
141 1 0

Exit code 141 来自false 过早终止管道 (SIGPIPE) 的事实。

这基本上只是使用冒号作为分隔符将子外壳的$PIPESTATUS 数组附加到存储的值(任何非数字都可以;我选择了一个我不必转义的),然后将其拉出响应,用这些值填充$PIPESTATUS2 数组。删除最后的换行符是另一个 bashism。我们可以使用它作为分隔符,但是如果原始输出没有被换行符终止,那么它就会中断。

更简单的解决方案如果你只想要one of the exit codes

TEST=$( echo "ABC" | false | true; exit ${PIPESTATUS[0]} )
echo $?  # 141 from `echo "ABC"

更复杂的符合 POSIX 的解决方案(当您可以使用一些黑魔法时,不需要 $PIPESTATUS):在著名的 Csh Programming Considered Harmful 的 §1d 中搜索“考虑管道”咆哮,然后根据您的 POSIX 兼容需求进行调整。如果您是那种需要避免使用 bash 和真实语言的编码人员,那么这将是非常重要的,但具有很高的教育意义。

【讨论】:

  • 写得很好,但我几乎不会将 csh 批评称为“咆哮”!必读。
  • 两者兼有。
  • 我只是喜欢最后退出/返回${PIPESTATUS[0]}的快速技巧
猜你喜欢
  • 2014-01-08
  • 1970-01-01
  • 2016-09-08
  • 2011-10-15
  • 1970-01-01
  • 2022-08-14
  • 2012-03-20
  • 2012-02-23
  • 2011-08-13
相关资源
最近更新 更多