
我想捕獲管道中某處發生的命令的退出狀態前最後的位置。例如,如果管道類似於
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