私はいくつかの関数を備えたBashスクリプトに取り組んでいます。コマンドがゼロ以外の終了コードを返した場合、そのコードが明示的に処理されているコンテキスト(if
条件または||
代替の前など)を除いて、スクリプトを終了したいと思います。これを簡単にするために、スクリプトからサブシェルの使用をすべて削除し、見つかったすべてのエラー処理オプションを有効にしました。
残念ながら、エラーが抑制されている一般的なパターンがまだ発生しています。
関数内のコマンドがゼロ以外の終了コードを返すが、関数内の最後のコマンドではなく、関数が&&
式の最初の部分として呼び出されている場合、終了コードは無視されます。
#!/bin/bash
trap 'echo "Error occurred." && exit' ERR
set -o errexit; # -e
set -o errtrace; # -E
set -o pipefail;
first-step-fails() {
# These should be redundant, but are repeated to be certain and clear.
trap 'echo "Error occurred." && exit' ERR
set -o errexit; # -e
set -o errtrace; # -E
set -o pipefail;
false; # exit code 1 (failure)
true; # exit code 0 (success)
echo "A is executed.";
}
first-step-fails && echo "B is executed.";
A is executed.
B is executed.
echo
の呼び出し後にfalse
sが実行されるとは思っていませんでした。
関数が&&
式で呼び出されない場合、エラーはトラップされます。
#!/bin/bash
trap 'echo "Error occurred." && exit' ERR
set -o errexit; # -e
set -o errtrace; # -E
set -o pipefail;
first-step-fails() {
# These should be redundant, but are repeated to be certain and clear.
trap 'echo "Error occurred." && exit' ERR
set -o errexit; # -e
set -o errtrace; # -E
set -o pipefail;
false; # exit code 1 (failure)
true; # exit code 0 (success)
echo "A is executed.";
}
first-step-fails ### && echo "B is executed.";
Error occurred.
失敗が関数の最後のステップである場合、エラーはトラップされませんが、もちろん関数はゼロ以外の終了ステータスを渡し、外側のecho
を抑制します。
#!/bin/bash
trap 'echo "Error occurred." && exit' ERR
set -o errexit; # -e
set -o errtrace; # -E
set -o pipefail;
first-step-fails() {
# These should be redundant, but are repeated to be certain and clear.
trap 'echo "Error occurred." && exit' ERR
set -o errexit; # -e
set -o errtrace; # -E
set -o pipefail;
false; # exit code 1 (failure)
### true; # exit code 0 (success)
### echo "A is executed.";
}
first-step-fails && echo "B is executed.";
(no output)
&&
式の左側で呼び出される関数内で呼び出されたコマンドからゼロ以外の終了ステータスが返された場合、bashスクリプトを終了させるにはどうすればよいですか?
私はmacOS(組み込みGNU Bash 4.4.23)でテストしていますが、Alpine Linux(パッケージ化されたGNU Bash4.4)でも機能するソリューションが必要です。 19)。
このset -e
の説明のように私には見えます:
失敗したコマンドが... &&または||で実行されたコマンドの一部である場合、シェルは終了しません。リスト
は、「&&リストの一部」を自由に解釈して、関数呼び出し内のすべてのコマンドを含めます。その結果、関数内の単純な失敗したコマンドでさえ、&&
チェーンで呼び出されたときにERRトラップをトリガーしません。
関数のコマンドの1つが失敗したときにその実行を停止する必要がある場合、1つの可能性は、それらすべてをブロック内でチェーンすることです。
first-step-fails() {
{
true &&
false &&
true;
} || exit 1
echo "A is executed.";
}
first-step-fails && echo "B is executed.";
...結果は出力されず、戻りコードは1になります。