パイプラインのどこかで発生するコマンドの終了ステータスをキャプチャしたいと思います。今後最終位置。たとえば、パイプラインが次のような場合
command_1 ... | command_2 ... | command_3 ... | ... | command_n
command_1
...、command_2
またはなどの終了ステータスをキャプチャする方法を知りたいです。 (もちろんcommand_3
キャプチャされた終了状態は簡単です。)command_n
また、重要な場合、このパイプはzshシェル関数内で発生します。
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、以下はパイプラインに2つのコマンドしかない操作の例です。
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]
あなたのアプローチがうまくいかないのは、各パイプが別々のサブシェルで実行され、サブシェルが終了すると、独自の変数が破壊されるためです。
PIPESTATUS
ちなみに(大文字)形式ですbash
。
答え2
mispipe
すべてのシェルで動作します。通常のパイプと比較して、構文は次のように動作します。
mispipe true false ; echo $? # returns exit code of 1st command `true`
true | false ; echo $? # returns exit code of 2nd command `false`
出力:
0
1
プログラムが2つ以上の場合の対処方法:
# this still returns exit code of 1st command `true`
mispipe true 'false | false | false' ; echo $?
出力:
0
可視性が不足しているにもかかわらず、|
まだパイプのように動作します。
yes | mispipe head 'wc -c'
出力:
20