Bashスクリプト内のコマンドがゼロ以外のステータスで終了したかどうかを知りたいです。
set -e
機能に似たものが必要ですが、コマンドがゼロ以外のステータスで終了したときに終了したくない点が異なります。スクリプト全体を実行したいのですが、次のいずれかを知りたいです。
a)すべてのコマンドが終了ステータス0で終了しました
-または-
b)1つ以上のコマンドがゼロ以外のステータスで終了しました
例:次の場合:
#!/bin/bash
command1 # exits with status 1
command2 # exits with status 0
command3 # exits with status 0
3つのコマンドすべてを実行したい。スクリプトを実行した後、少なくとも1つのコマンドがゼロ以外のステータスで終了したことを示したいと思います。
ERRにトラップを設定します。
#!/bin/bash
err=0
trap 'err=1' ERR
command1
command2
command3
test $err = 0 # Return non-zero if any command failed
エラーが発生した場所に関するデータを取得するために、少し内省することもできます。
#!/bin/bash
for i in 1 2 3; do
eval "command$i() { echo command$i; test $i != 2; }"
done
err=0
report() {
err=1
echo -n "error at line ${BASH_LINENO[0]}, in call to "
sed -n ${BASH_LINENO[0]}p $0
} >&2
trap report ERR
command1
command2
command3
exit $err
DEBUG
疑似信号のトラップを使用して、次のようなことを試みることができます。
trap '(( $? && ++errcount ))' DEBUG
DEBUG
トラップは、「すべての単純コマンド、for
コマンド、case
コマンド、select
コマンド、すべての算術for
コマンドの前に実行されます。シェル関数で最初のコマンドが実行される前」(マニュアルからの引用)。
したがって、このトラップを追加し、最後のコマンドとしてエラーカウントを出力すると、適切な値が得られます。
#!/bin/bash
trap '(( $? && ++errcount ))' DEBUG
true
false
true
echo "Errors: $errcount"
戻り値 Errors: 1
と
#!/bin/bash
trap '(( $? && ++errcount ))' DEBUG
true
false
true
false
echo "Errors: $errcount"
印刷Errors: 2
。トラップが実行されるため、最後のステートメントは実際には2番目のfalse
を説明する必要があることに注意してくださいbeforeコマンドであるため、2番目のfalse
の終了ステータスはecho
行のトラップが実行されるときにチェックされます。
あなたの要件に対応する既製のソリューションがあるかどうかはわかりません。私はこのような関数を書きます:
function run_cmd_with_check() {
"$@"
[[ $? -ne 0 ]] && ((non_zero++))
}
次に、この関数を使用して、追跡が必要なすべてのコマンドを実行します。
run_cmd_with_check command1
run_cmd_with_check command2
run_cmd_with_check command3
printf "$non_zero commands exited with non-zero exit code\n"
必要に応じて、機能を拡張して、失敗したすべてのコマンドを配列に格納し、最後に出力することができます。
詳細については、この投稿を参照してください: Bashでのエラー処理
DEBUG
トラップは次のように使用できます。
trap 'code+=$?' DEBUG
code=0
# run commands here normally
exit $code
あなたは魔法の変数を持っています$?
最後のコマンドの終了コードを通知するbashで利用可能:
#!/bin/bash
command1 # exits with status 1
C1_output=$? # will be 1
command2 # exits with status 0
C2_output=$? # will be 0
command3 # exits with status 0
C3_output=$? # will be 0
コマンドのリストを配列に配置してから、コマンドをループすることができます。エラーコードを返すものはすべて、後で表示できるように結果を保持します。
declare -A results
commands=("your" "commands")
for cmd in "${commands[@]}"; do
out=$($cmd 2>&1)
[[ $? -eq 0 ]] || results[$cmd]="$out"
done
次に、ゼロ以外の終了コードを確認します。
for cmd in "${!results[@]}"; do echo "$cmd = ${results[$cmd]}"; done
results
の長さが0の場合、コマンドのリストにエラーはありませんでした。
これにはBash4 +が必要です(連想配列の場合)
コマンドごとに、これを行うことができます。
if ! Command1 ; then an_error=1; fi
そして、すべてのコマンドに対してこれを繰り返します
いずれかが失敗した場合、最後にan_errorは1になります。
失敗の数が必要な場合は、最初にan_errorを0に設定し、$((an_error ++))を実行します。 an_error = 1の代わりに