最初のスクリプトで呼び出されたスクリプトがエラーコードで終了したときにスクリプトを実行し続けるにはどうすればよいですか?

最初のスクリプトで呼び出されたスクリプトがエラーコードで終了したときにスクリプトを実行し続けるにはどうすればよいですか?

私は失敗するまで2番目のスクリプトを繰り返し実行し、2番目のスクリプトのstdoutとstderrをキャプチャするbashスクリプトを作成しようとしています。私はその過程で直面したほとんどの問題を処理し、次のスクリプト(と呼ばれる)を使用しましたerror_checker.sh

#!/usr/bin/env bash

i=0

while [ $? -ne 1 ]
do
i=$[$i+1]
source script.sh &> log.txt
echo "This error occurred after $i run(s)." >> log.txt
done

繰り返したいスクリプトが呼び出され、script.sh次のコードがあります。

#!/usr/bin/env bash

 n=$(( RANDOM % 100 ))

 if [[ n -eq 42 ]]; then
    echo "Something went wrong"
    >&2 echo "The error was using magic numbers"
    exit 1
 fi

 echo "Everything went according to plan"

スクリプトerror_checker.shは、失敗した実行のstdoutとstderrを指定されたファイルlog.txtに出力できますが、スクリプトが行の2番目のスクリプトで終了した場合

source script.sh &> log.txt

したがって、ファイルに追加のエラーメッセージを追加することはできません。

しばらく検索したところ、これが2番目のスクリプトを実行したときにサブシェルを作成することに関連している可能性があることがわかりました。これは問題を解決することができますが、代わりにそれを行うと端末全体が./機能しなくなります。と入力すると停止します。sourcesource././error_checker.sh

どんなお手伝いのお手伝いもありがとうございました!

修正する: 現在の回答ありがとうございます!今私の主な問題は、source script.sh新しいシェルプロセス./script.shで実行するように変更すると、error_checker.sh端末全体がハングして使用できないことです。./これがすぐerror_checker.shに使用した場合にのみ正常に実行できる理由ですsource script.sh。何が起こるのか考えがありますか?

アップデート2: 端末全体が停止しているように見え、Ctrl + Cを押してプロセスを終了する必要がありましたが、まだlog.txtが生成されるように変更sourceしました。./ただし、使用バージョンは stdout と stderr が using を介してキャプチャされたことを示すsourcelog.txt を生成し、使用バージョンは log.txt を生成しました。何が起こったのか知っていますか?Something went wrong. The error was using magic numbers&>./Everything went according to plan. The error occurred after X run(s)

最終更新:以下のGlennの答えに基づいてコードを編集しましたが、うまくいきます。 whileループのechoコマンドは実際にはscript.phの終了ステータスを評価することができず、無限ループが生成されるようです。

#!/usr/bin/env bash

i=0

while [ $? -ne 1 ]
do
((i++))
./script.sh >& log.txt
done

echo "This error occurred after $i run(s)." >> log.txt

ベストアンサー1

スクリプトを受け取っているので、exit 1次のように変更してください。return 1

script.sh を「トップレベル」スクリプトとして実行する場合は、次のことができます。

if (( n == 42 )); then
    if [[ "$0" == "${BASH_SOURCE[0]}" ]]; then
        # I'm the "main" script
        exit 1
    else
        # I'm being sourced from some other script
        return 1
    fi
fi

もしあなたなら〜しなければならないsource(疑わしいがコードを確認する必要があります)を使用すると、スクリプトを変更できないため、サブシェルでコマンドをソースする必要があります。これは、exit最上位プログラムを実行している現在のシェルではなくサブシェルで終了することを意味します。

i=0
#     /--------------------------------\  parentheses create a subshell
while (source script.sh >> log.txt 2>&1)
do
    ((i++))
done
echo "This error occurred after $i run(s)." >> log.txt

これにより、以下を含むログファイルが生成されます。

Everything went according to plan
...
Everything went according to plan
Something went wrong
The error was using magic numbers
This error occurred after 302 run(s).

コードに関するいくつかの注意:

  • $[...]文書化されていない構文なので、使用されなくなる可能性があります。$((...))算術拡張または算術評価に使用されます((...))
  • $?終了状態ですか?より早いwhileループの2回目の繰り返しのコマンドはですechoecho標準出力(または指定されたファイル記述子)を書き込めない場合にのみゼロ以外の値が返されるため、無限ループが発生します。script.shの終了ステータスをテストしていないからです!
    • エラー状態の後にCtrl + Cを押す確率は約1%であるため、ログファイルに「良い」メッセージが含まれる確率は99%です。
  • &>寛容ではない:使用または>& fileより明確です>file 2>&1
  • 「次の後にエラーが発生しました。」メッセージを印刷したい可能性が高いです。外部回報

おすすめ記事