ファイルが更新されるのを待ちますが、時間しきい値を超えると終了するwhileループを持つBashスクリプト

ファイルが更新されるのを待ちますが、時間しきい値を超えると終了するwhileループを持つBashスクリプト

私はbashをかなりよく知っているので、この質問が解決しやすい場合はお詫び申し上げます。詳細が必要な場合はお知らせください。以下のスクリプトは、Pythonワークフローを起動し、ワークフローの終了時にresults.jsonファイルが更新されるのを待つ大きなスクリプトの一部です。

使ってみました。

{
    sleep 1m
    kill $$
}&

ただし、results.jsonファイルが1分以内に更新されると、エラーが生成されます。

Kill:(90015) - そのプロセスはありません。

スクリプトは次のとおりです。

#! /bin/bash
export DISPLAY=:0.0

export outputfile=results.json

if [[ ! -e $outputfile ]]; then
    touch $outputfile
fi

OldTimestamp=$(date -r $outputfile)

{
    sleep 1m
    kill $$
}&

NewTimestamp=$OldTimestamp; 
while [ "$NewTimestamp" = "$OldTimestamp" ]; do 
   sleep 0.1
   NewTimestamp="$(date -r $outputfile)" 
done

答え1

ただ取り除きたいならKill:(90015) - そのプロセスはありません。エラー、プロセスを終了する前に、プロセスがまだ実行中であることを確認できます。

{
    sleep 1m
    ps -p $$ > /dev/null && kill $$
}&

しかし、実際に私はkillをまったく使用しません。 whileループの相互作用の数を追跡し、適切な反復数の後にループを中断することができます。

NewTimestamp=$OldTimestamp; 
iterations=0
while [ "$NewTimestamp" = "$OldTimestamp" ] && [ $iterations -lt 600 ]; do
   sleep 0.1
   NewTimestamp="$(date -r $outputfile)"
   let iterations++
done

ファイルが更新されていない場合、ゼロ以外の終了コードで終了するには、次のように追加します。

if [ "$NewTimestamp" = "$OldTimestamp" ] ; then 
    echo "results.json was not updated" >&2
    exit 1
fi

またはそのようなもの。

答え2

この方法で実行する必要がある場合、results.jsonを正常に作成すると次のエラーが発生する理由は次のとおりです。 sleep と Kill を中かっこ内に入れると、これをグループコマンドと呼びます。中かっこの後に&記号を入れると、サブシェルの背景に配置されます($$グループコマンドが解析され、実行されると現在のpidに変更されるため、まだ機能します)。 Pythonプログラムが正常に完了すると、sleepとkillを実行する子プロセスが消えるように指示するものはありません。スリープモードの有効期限が切れると、kill が実行され、元のスクリプトが実行されなくなったため、「該当するプロセスはありません」と文句を言います。

操作する方法は次のとおりです。成功した結果が得られたら実行してくださいkill %1。その後、睡眠が取り除かれ、死にます。

OldTimestamp=$(date -r $outputfile)

{
    sleep 1m
    kill $$
}&

NewTimestamp=$OldTimestamp; 
while [ "$NewTimestamp" = "$OldTimestamp" ]; do 
   sleep 0.1
   NewTimestamp="$(date -r $outputfile)" 
done

echo "I have found my $outputfile and am done"
kill %1   # Kill off the subprocess which would have killed off this script

上記で「必要であれば…」と言った理由は、人々がこの文章を書く一般的な方法ではないからです。通常、このコマンドを使用してtimeoutresults.jsonを生成する必要があるPythonスクリプトを実行します。これにより、その実行状態を確認し、成功しなかった場合はスクリプトを終了できます。

また、タイムアウト期間に達した後にレポートジェネレータを終了できるという利点もあります。上記の方法はそうではありません。レポートジェネレータが遅い場合は、トップレベルのスクリプトが完了した後もバックグラウンドで実行され続けることがわかります。 (システムがどのように機能するかについていくつかの仮定をしていますが、通常、この方法ではトップレベルのスクリプトのみを停止し、スクリプト自体で開始されたものは停止しません。)

Pythonスクリプトが「makereport.py」の場合は、次のことができます。

#!/bin/bash
export outputfile=results.json
OldTimestamp=$(date +"%s" -r $outputfile)  # Use %s so we have a simple integer

timeout 1m makereport.py
if [[ $? -ne 0 ]]; then
    echo "makereport.py failed"
    exit 1
fi

# At this point you can either assume report.json was created, or you
# can check it like you did before
CurTimestamp=$(date +"%s" $outputfile)
if [[ $CurTimestamp = $OldTimestamp ]]; then
    echo "makereport.py finished successfully, but a new report was not generated"
fi
echo "Verified we have a new report.json ready to go"

関連情報