Skip to content

Instantly share code, notes, and snippets.

@katzchang
Last active September 21, 2021 02:30
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save katzchang/f41ab26b196fbba5f91d59778011e082 to your computer and use it in GitHub Desktop.
Save katzchang/f41ab26b196fbba5f91d59778011e082 to your computer and use it in GitHub Desktop.
処理が成功するまで実行しつづける - @katzchang.gist

処理が成功するまで実行しつづける

インスタンスの起動スクリプトとかを書いてるときによく欲しいと思うやつです。

例えば、 service nginx start が実行されたあとに curl -i localhost | grep "200 OK" とかをすると、サービスがそれなりに動いていることが確認できてよかったりするのですが、あまりにも直後だとサーバの起動が間に合わず、curl が失敗してしまいます。nginxだとまだましだけど、アプリケーションサーバだとそれなりに時間がかかったりする。

古典的な解決方法は、 sleep 30 です。簡単だけど、アプリケーションが巨大になってくると30秒では起動しないこともある。じゃぁ sleep 60 が妥当か?でも、サーバインスタンスの起動スクリプト全体はできるだけ早く立ち上がってほしい。困った。

なので、curlが成功するまで叩き続ける、みたいなスクリプトに仕上げたくなるわけです。

書いたらそんなに苦労しなかった。

service nginx start
until curl -i localhost | grep "200 OK"
  do
    sleep 5
  done

こんなかんじ。makefileの中で使ったりするために1行で書くと、

until (curl -i localhost | grep "200 OK") do sleep 5; done

リトライの頻度を増やしたいときは、 sleep 1 とかにしましょう。それ以下は usleep 500 とか、もしくは sleep 0.1 とかも結構できるようです(要確認)。

ずっと実行され続けてつらい?timeoutと組み合わせてみましょう。untilなどと組み合わせるのが辛かったので、shコマンド経由で:

timeout 60 sh -c 'until (curl -i localhost | grep "200 OK") do sleep 1; done'

簡単。untilの条件が複雑になるとクオートのエスケープとかが辛くなるので、そのときは別スクリプトに分割していきましょう。

いままでは bash retry until とかでググってたのであんまり良い答えにたどり着かなかったけど、これでええんやっていうことを昨日気づいたので、そのメモでした。

追記

インターバルを増やしていく場合:

i=1; until (curl -i localhost | grep "200 OK") do sleep $i; i=$(($i*2)); done

難しくはない。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment