如何捕捉管道中非最終命令的退出狀態?

如何捕捉管道中非最終命令的退出狀態?

我想捕獲管道中某處發生的命令的退出狀態最後的位置。例如,如果管道類似於

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

相關內容