web-dev-qa-db-ja.com

bashスクリプトのいずれかのコマンドが失敗したかどうかを確認する方法(ゼロ以外の終了ステータス)

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つのコマンドがゼロ以外のステータスで終了したことを示したいと思います。

14
Rob Bednark

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
8
William Pursell

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行のトラップが実行されるときにチェックされます。

3
Benjamin W.

あなたの要件に対応する既製のソリューションがあるかどうかはわかりません。私はこのような関数を書きます:

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でのエラー処理

1
codeforester

DEBUGトラップは次のように使用できます。

trap 'code+=$?' DEBUG
code=0

# run commands here normally

exit $code
0
Grisha Levit

あなたは魔法の変数を持っています$?最後のコマンドの終了コードを通知する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
0
hjpotter92

コマンドのリストを配列に配置してから、コマンドをループすることができます。エラーコードを返すものはすべて、後で表示できるように結果を保持します。

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 +が必要です(連想配列の場合)

0
dawg

コマンドごとに、これを行うことができます。

if ! Command1 ; then an_error=1; fi 

そして、すべてのコマンドに対してこれを繰り返します

いずれかが失敗した場合、最後にan_errorは1になります。

失敗の数が必要な場合は、最初にan_errorを0に設定し、$((an_error ++))を実行します。 an_error = 1の代わりに

0
Mike Wodarczyk