ksaitoの日記

日々試したことの覚え書き

シェルでタイムアウトを設けて何かを待つ処理をワンライナーで書く

シェルでタイムアウトを設けて何かを待つ処理をワンライナーで書いてみました。

アプリケーションサーバの起動のあとに何か実行する必要がある場合、起動の完了を待つ必要があります。 同期呼び出しやコールバックなどが設定できない場合は、ログやポートを定期的に監視する必要があります。

ここでは、サンプルとして、時刻の秒が48秒になったら何か処理することを想定します。

下記のように実装しました。

$ timeout 30 bash -c 'while true; do date +'%S' | grep 48 &&  break; sleep 1; done'
48
$ echo $?
0
$ timeout 3 bash -c 'while true; do date +'%S' | grep 48 &&  break; sleep 1; done'
$ echo $?
124
$

詳細

ワンライナーの詳細です。

条件の判定

何かの状態になったかを確認する専用のコマンドが提供されていない場合は、grepdiffが便利です。これらのコマンドは、終了ステータスで条件を満すと0、満たさないと0以外を返します。

時刻が48秒かを判別するには、下記のようにします。

date +'%S' | grep 48
echo $?

判定条件を毎秒繰り返す

while文を使って、条件の判定を毎秒繰り返す事ができます。

$ while true
> do
>   date +'%S' | grep 48
>   sleep 1
> done

この処理では、条件を満たしても終了しないので、終了処理を追加します。

&&は、実行したコマンドが成功した時に実行するコマンドを指定できます。 コマンドが成功(=条件を満たした)場合にbreakコマンドを実行してループを抜けます。

$ while true
> do
>   date +'%S' | grep 48 &&  break
>   sleep 1
> done
48
$

タイムアウトを設ける

timeoutコマンドを使って一定時間経過しても条件を満たさない場合は、エラーとなるようにします。

条件を満たしたか、タイムアウトになったかは、終了ステータスで判別できます。

$ timeout 60 bash -c 'while true; do   date +'%S' | grep 48 &&  break;   sleep 1; done'
48
$ echo $?
0
$ timeout 2 bash -c 'while true; do   date +'%S' | grep 48 &&  break;   sleep 1; done'
$ echo $?
124
$