![如何捕获管道中非最终命令的退出状态?](https://linux22.com/image/97035/%E5%A6%82%E4%BD%95%E6%8D%95%E8%8E%B7%E7%AE%A1%E9%81%93%E4%B8%AD%E9%9D%9E%E6%9C%80%E7%BB%88%E5%91%BD%E4%BB%A4%E7%9A%84%E9%80%80%E5%87%BA%E7%8A%B6%E6%80%81%EF%BC%9F%20.png)
我想捕获管道中某处发生的命令的退出状态前最后的位置。例如,如果管道类似于
command_1 ... | command_2 ... | command_3 ... | ... | command_n
...我想知道如何捕获command_1
、 或command_2
、 或等的退出状态。(当然,command_3
捕获 的退出状态很简单。)command_n
另外,如果重要的话,这个管道发生在 zsh shell 函数内部。
我试图command_1
用类似的东西来捕获退出状态
function_with_pipeline () {
local command_1_status=-999999 # sentinel value
{ command_1 ...; command_1_status=$? } | command_2 ... | ... | command_n
...
}
...但是运行管道后,command_1_status
变量的值仍然是哨兵值。
FWIW,这是一个工作示例,其中管道只有两个命令:
foo ... | grep ...
foo
是为本示例而定义的函数,如下所示:
foo () {
(( $1 & 1 )) && echo "a non-neglible message"
(( $1 & 2 )) && echo "a negligible message"
(( $1 & 4 )) && echo "error message" >&2
return $(( ( $1 & 4 ) >> 2 ))
}
foo
目标是捕获管道中调用的退出状态。
该函数function_with_pipeline
实现了我上面描述的(最终无效的)策略来执行此操作:
function_with_pipeline () {
local foo_status=-999999 # sentinel value
{ foo $1; foo_status=$? } | grep -v "a negligible message"
printf '%d\ndesired: %d; actual: %d\n\n' $1 $(( ( $1 & 4 ) >> 2 )) $foo_status
}
下面的循环练习该function_with_pipeline
函数。输出显示局部变量的值foo_status
最终与开始时没有什么不同。
for i in $(seq 0 7)
do
function_with_pipeline $i
done
# 0
# desired: 0; actual: -999999
#
# a non-neglible message
# 1
# desired: 0; actual: -999999
#
# 2
# desired: 0; actual: -999999
#
# a non-neglible message
# 3
# desired: 0; actual: -999999
#
# error message
# 4
# desired: 1; actual: -999999
#
# error message
# a non-neglible message
# 5
# desired: 1; actual: -999999
#
# error message
# 6
# desired: 1; actual: -999999
#
# error message
# a non-neglible message
# 7
# desired: 1; actual: -999999
#
local
如果我省略定义中的声明,我会得到相同的结果foo_status
。
答案1
有一个特殊的数组pipestatus
,zsh
所以尝试
command_1 ... | command_2 ... | command_3
和
echo $pipestatus[1] $pipestatus[2] $pipestatus[3]
您的方法不起作用的原因是因为每个管道都在单独的子shell中运行,其自己的变量一旦退出子shell就会被销毁。
仅供参考,它是PIPESTATUS
(大写字母)格式bash
。
答案2
mispipe
适用于任何 shell。语法(与常规管道相比)的工作原理如下:
mispipe true false ; echo $? # returns exit code of 1st command `true`
true | false ; echo $? # returns exit code of 2nd command `false`
输出:
0
1
如果有两个以上的程序该怎么办:
# this still returns exit code of 1st command `true`
mispipe true 'false | false | false' ; echo $?
输出:
0
尽管缺少可见的|
,它仍然表现得像管道应该:
yes | mispipe head 'wc -c'
输出:
20