1
0

More than 3 years have passed since last update.

mysql server(mysqld)の起動をn回リトライして待つshellコマンドとmakefileを書いた

Last updated at Posted at 2020-01-26

この記事の対象読者

  • mysql serverの起動を待つスクリプトが欲しい
  • docker-compose で mysqlを使っているが上手く初期化できない

    • なぜか初期化処理がbuildプロセスだけ失敗する
  • 以下のエラーでググってhostを直しても一向に直らない

ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 0

TL;DR

mysql server(mysqld) の起動を待つ処理を入れましょう。
通常であればこれでいいと思います

$ mysqladmin --wait --count 3 ping || exit 1

docker-composeだとちょっと癖があるので上記以外で対処します。

shellはこんな感じ

// 5回繰り返す
for i in 1 2 3 4 5; do mysqladmin ping &>/dev/null && break || sleep 1  && [ 5 -eq $i ] && exit 1; done

// 出来るまで繰り返す
until (mysqladmin ping &>/dev/null) do echo '.' && sleep 1; done

人によってはこっちでもいいかも: 処理が成功するまで実行しつづける@katzchang

makefile

mysql/lifecheck: 
    until (mysqladmin ping &>/dev/null) do echo '.' && sleep 1; done

mysql/wait:
    which mysqladmin
    @echo "waiting boot mysql..."
    $(MAKE) mysql/lifecheck

mysql server(mysqld)の起動を待つshellコマンドとmakefileを書いた

mysql server(mysqld)で起動直後にサーバ接続ができないケースがあった。

困ったので接続できるまでn回リトライし続けるshellコマンドと makefileを書いた。

無限に待ちたいわけではない ので今回は n回 と言う制約を持たせる。

僕はdocker-composeを使っているのでそれ前提で話をすすめる。

同じく困ってる人はいるんじゃないかな、と思ったのでメモる。

docker-compose で mysqlコンテナへ起動直後に接続できない!

今回は docker-compose でmysqlのコンテナを立てるケースを考える。

コンテナのbuild直後にmysqlに接続できないことがあった。

これでは、buildしたあとにエラーが起きDBの初期化処理が続けてできない。

マイグレーションもできないし、設定もできなくて困る。

コンテナ起動直後はmysql server(mysqld)が立ち上がっていない。

docker container が立ち上がった直後は mysql server(mysqld) がまだ起動していない。

mysql client(mysqladmin) から接続を試みるとこのエラーが出る。

ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 0

エラーメッセージでぐぐるとhostの設定が足りないとの記事が出てきてめちゃめちゃハマった。

そうじゃない。

sleep n秒が1番簡単な解決方法

マイグレーションなどの処理の前に sleep 60 する

mysql server のデーモン起動(mysqld)まで待てばいいのでこれでok。

起動までリトライしたい

60秒を超えてmysql serverが起動した場合、 sleep 60 だと対応できない。
時間 or n回 リトライするような作りになっていればよい。

How do I write a retry logic in script to keep retrying to run it upto 5 times? より拝借

for i in 1 2 3 4 5; do command && break || sleep 1; done

これを使えば 5回, 1秒ごとに 成功するまでcmdを繰り返す 状態を作り出せる。

mysql serverのlifecheckは mysqladmin ping で行える。

for i in 1 2 3 4 5; do mysqladmin ping && break || sleep 1 ; done

これだと mysql serverが起動してようとしてなろうと次の処理へ行ってしまう。

そこで最終ループのときに exit 1 で抜けるようにした


for i in 1 2 3 4 5; do mysqladmin ping && break || sleep 1 && [ 5 -eq $i ] && exit 1; ; done

makefile で rangeを指定する

build中のタスクランナーとしてmakefileを使っている。

n回処理する記述は以下のように書ける。


RETRY_COUNT=30
RETRY_RANGE=$(shell seq 1 $(RETRY_COUNT) | xargs)

mysql/lifecheck: 
    for i in $(RETRY_RANGE); do mysqladmin ping &>/dev/null && break || echo '.' && sleep 1  && [ $(RETRY_COUNT) -eq $$i ] && exit 1; done

mysql/wait:
    which mysqladmin
    @echo "waiting boot mysql..."
    $(MAKE) mysql/lifecheck

無限に続ける方はこっち。こっちの方が仕事が明確

mysql/lifecheck: 
    until (mysqladmin ping &>/dev/null) do echo '.' && sleep 1; done

mysql/wait:
    which mysqladmin
    @echo "waiting boot mysql..."
    $(MAKE) mysql/lifecheck

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0