如何捕获管道中非最终命令的退出状态?

如何捕获管道中非最终命令的退出状态?

我想捕获管道中某处发生的命令的退出状态最后的位置。例如,如果管道类似于

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

有一个特殊的数组pipestatuszsh所以尝试

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

相关内容