子プロセスがゼロ以外の終了コードで終了すると、親スクリプトは続行されます。

子プロセスがゼロ以外の終了コードで終了すると、親スクリプトは続行されます。

別のスクリプトを呼び出すスクリプトがあります。サブスクリプトが失敗した場合、親スクリプトも失敗したいと思います。

下付き文字にはchild_1.sh次の内容があります。

if [ $SOME_BAD_CONDITION ] ; then
  echo "Error message...."
  exit 1
fi

親には次のものがあります。

#!/bin/bash
set -e
#...
bash ./child_1.sh
echo "continuing to next step..."
bash ./child_2.sh
bash ./child_3.sh
#...

$SOME_BAD_CONDITION常にこれが起こり、スクリプトがエラーメッセージで期待どおりに終了するように環境を設定しました。する印刷しますが、親スクリプトは続行します。「続行...」メッセージを印刷し、次のスクリプトの実行を開始します。

set -e親スクリプトが失敗することを保証するゼロ以外の終了コードを持つサブスクリプトがある場合、それは起こらないと思いました。ここで私が何を間違っているのかわかりません...

バッシュバージョン:4.2.25


修正する:

私はエコを試してみます$?

bash ./child_1.sh
echo $?
echo "continuing to next step..."

出力は次のとおりです。

エラーメッセージ....
0
次のステップに進みます...

子プロセスの終了コードが親プロセスに移動しないのはなぜですか?


回答:元のコードスニペットは不完全です。これはexit 1、ティーにパイプで接続されたコードブロック内にあります。投稿をしようとしていますきれい、短いコード例では、これがどれほど重要かわからなかったので、これを無視します(私は初めてbashスクリプトに触れました)。詳しくは、私が投稿した回答をご覧ください。

答え1

したがって、下付き文字の詳細を十分に投稿していない間違いを犯した可能性があります。この質問の目的のために単純化しましたが、おそらく多すぎるでしょう。ステートメントは、ロギングにパイプされるexitコードブロック({および間)内に隠されています。}tee

{
  #...
  if [ $SOME_BAD_CONDITION ] ; then
    exit 1
  fi
  #...
} | tee -a $LOGFILE
echo "script ended at $date">>$LOGFILE

私が理解したところ、最後のスクリプトは0を返すので、この添え字から常に戻りコード0を取得しますecho。少し調べて見つけました。$パイプラインステータス。これを使用して、スクリプトが終了コード1で終了しようとしたときに親スクリプトに渡すことができました。

{
  #...
} | tee -a $LOGFILE
EXIT_CODE=${PIPESTATUS[0]}
echo "script ended at $date">>$LOGFILE
exit $EXIT_CODE

Johnの提案と組み合わせて動作するように見える解決策があります。

答え2

子プロセスが正しい0/0ではなく終了コードルールで終了し、順次実行されることを考慮すると、演算子を使用できると言いたいと思います&&

#!/bin/bash

./child_1.sh
[[ $? -ne 0 ]] && exit # Exit if non-zero exit code
./child_2.sh
./child_3.sh
./child_4.sh
exit 0

ここでの[[ $? -ne 0 ]] && exit動作は次のとおりです。

if [ $? -ne 0 ]; then # If: last exit code is non-zero
    exit
fi

通話の間にやることがない場合は、次のものを使用することもできます。

#!/bin/bash
./child_1.sh && ./child_2.sh && ./child_3.sh && ./child_4
exit $?

オペレータは&&次のように振る舞います。段落AND演算子, 0 終了コードはtrueブール値に非常に似ています。チェーン内でいつでもスクリプトがゼロ以外の値で終了した場合、スクリプトは&&失敗し、後続のスクリプトを呼び出すべきではありません。

答え3

問題は、下付き文字にエラーを投げる方法に由来するようです。

Man setで、「単純なコマンド(上記のSHELL GRAMMARを参照)がゼロ以外の状態で終了する場合。失敗したコマンドがwhileまたはUntilキーワード(テストの一部)の直後のコマンドリストの一部である場合、シェルは終了ifステートメントで&&または||がリストの一部であるか、コマンドの戻り値が!

set -e を使用する代わりに Trap ステートメントを使用し、エラーを発生させます。 (必要に応じて条件付き終了を使用してください。

バラよりhttp://mywiki.wooledge.org/BashFAQ/105

関連情報