何千回も実行されるforループを含むbashスクリプトを実行しています。このforループのどこかでコードが頻繁に停止することがあります。 (私が見た最も低い反復は32回で、ほとんどは4000回程度で停止します。コードは5000回実行する必要があり、時にはタスクを完了することもあります。)この問題をデバッグしたいと思います。明らかに、コマンドウィンドウに数十万行のコードを手動で入力し、停止するのを待ちたくありません。
最後に実行したか実行しようとした行が何であるかを見つける簡単な方法はありますか? (何かが間違っていると、端末が停止しているように見えます。時にはシステム全体が動作を停止して再起動するためにリモートリセットが必要になることに注意してください。)これはechoの機能かもしれないと思いました。私が見つけたこの質問と回答しかし、「コマンドがパーサーの観点からスクリプトの特定の行を表す場合」が何を意味するのかわかりません。したがって、適用される場合です。また、このコードが実際に何をしているのかは非常に混乱しています。このコードが役立つ場合はありがとうございます。
これが私が探している答えですか?この問題に対する他の解決策はありますか?
答え1
まず、問題が発生する繰り返しを確認する必要があります。運が良ければいつも同じです。とにかくそうしない場合は、繰り返し回数を数えて印刷するか、ファイルに書き込む必要があります。
exec 3>/my/logfile
iter=0
while whatevercondition; do
((iter++))
echo "$iter" >&3
done
同じ繰り返しで問題が常に発生する場合は、デバッグ出力を有効にしてから次の操作を行う必要があります。
CRASH_ITER=12345
iter=0
while whatevercondition; do
((iter++))
if [ "$iter" -eq "$CRASH_ITER" ]; then
set -vx
fi
done
再現不可能なエラー
エラーを特定の反復に絞り込むことができない場合は、bashにデバッグ出力全体をファイルに書き込むことができます。
bash -vx ./script.sh 2>debug.txt
答え2
Bashスクリプトの上部にこれを追加する場合:
関数 DEBUG_TRAP() { 組版-p BASH_SOURCE;組版-p BASH_LINENO; } トラップ DEBUG_TRAP INT
プロセスにINT信号を送信すると、プログラムの場所に関する情報を取得できます。
kill -INT process-number
次のように、bashスクリプトからプロセス番号を取得できます。
エコ$$
これを実行しても出力が出ない場合は、スクリプトが出力をリダイレクトしたか、スクリプトが進行中です。 lsof は出力リダイレクトについて通知します。メモ進捗状況に関する情報が提供されます。
答え3
ループが次の場合:
i=0
while [ "$((i+=1))" -le 5000 ] &&
set >iter.log
do monte_carlo
done
各反復は、毎回すべてのシェル変数の現在の値を一覧表示するファイルを上書きします。したがって、488の実行中に中断された場合繰り返しログファイルは、$i
繰り返しの開始時に488の値と他のすべてのシェル変数を記録します。
失敗した行番号を追跡するには、さらに一歩進むことができます。
i=0 PS4='$LINENO : '; set -x
while [ ... ] &&
set >iter.log
do ...
done 2>>iter.log
これにより、繰り返すたびにファイルが上書きされますが、実行された各行のデバッグ出力も追加され、ファイルにその行番号が含まれます。