別のスクリプトを呼び出すスクリプトがあります。子スクリプトが失敗した場合は、親も失敗したいと思います。
子スクリプトで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
は常に発生し、スクリプトは期待どおりに終了し、エラーメッセージdoesが出力されますが、親スクリプトは続行します。「continuing ...」というメッセージが出力され、次のスクリプトの実行が開始されます。
set -e
は、ゼロ以外の終了コードを持つ子スクリプトが存在する場合、私の親スクリプトが確実に失敗するようにしますが、そうではないようです。ここで何が間違っているのかわかりません...
bashバージョン:4.2.25
更新:
エコーしてみました$?
:
bash ./child_1.sh
echo $?
echo "continuing to next step..."
出力は次のようになります。
エラーメッセージ.... 0 次のステップに進みます...
なぜ子の終了コードが親にならないのですか?
回答:元のコードスニペットは不完全でした。 exit 1
は、ティーにパイプされたコードブロック内にありました。 clean、shortコードサンプルを投稿しようとしたが、それがどれほど重要であるかを理解していなかったため、これを無視した(bashスクリプトはまだかなり新しい)。詳細については、投稿した回答を参照してください。
したがって、子スクリプトに関する十分な詳細を投稿しないと、エラーが発生した可能性があります。この質問のために簡略化しましたが、多すぎる可能性があります。 exit
ステートメントがコードブロック内に埋め込まれました({
および}
)ロギングのためにtee
にパイプされました:
{
#...
if [ $SOME_BAD_CONDITION ] ; then
exit 1
fi
#...
} | tee -a $LOGFILE
echo "script ended at $date">>$LOGFILE
私の理解から、最後のecho
が0を返していたため、この子スクリプトから常に戻りコード0を受け取りました。調査を行ったところ、 $ PIPESTATUS が見つかりました。これを使用して、スクリプトが終了コード1で終了しようとしたときに、親スクリプトに渡されることを確認できました。
{
#...
} | tee -a $LOGFILE
EXIT_CODE=${PIPESTATUS[0]}
echo "script ended at $date">>$LOGFILE
exit $EXIT_CODE
ジョンの提案と組み合わせると、うまくいくように見える解決策があります。
あなたの子プロセスは適切なゼロ/非ゼロの終了コード規則で終了し、それらを順番に実行するとすれば、&&
演算子:
#!/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演算子 のように動作し、ゼロの終了コードはtrue
ブール値によく似ています。チェーン内の任意の時点で、スクリプトがゼロ以外で終了すると、&&
は失敗し、後続のスクリプトは呼び出されません。
問題は、子スクリプトでエラーをスローする方法に起因するようです。
Man setから、「単純なコマンド(上記のシェルGRAMMARを参照)がゼロ以外のステータスで終了した場合。失敗したコマンドが、テストの一部であるwhileまたはuntilキーワードの直後のコマンドリストの一部である場合、シェルは終了しません。 ifステートメント、&&または||リストの一部、またはコマンドの戻り値が!
Set -eを使用する代わりに、trapステートメントを使用してエラーをスローします。 (条件付き出口を使用する必要がある場合。