PostgreSQL が起動したかどうか簡単に確認する (ping)

Posted on
qiita ShellScript PostgreSQL Docker

この記事はQiitaの記事をエクスポートしたものです。内容が古くなっている可能性があります。

PostgreSQL は、プロセスを起動してから SQL クエリ・外部入力を受け付けるようになるまで若干のタイムラグが有ります。特に Docker コンテナで起動した場合、自分の環境では5秒程度待つことになります。

The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.

The database cluster will be initialized with locale "en_US.utf8".
The default database encoding has accordingly been set to "UTF8".
The default text search configuration will be set to "english".

...

LOG:  autovacuum launcher shutting down
LOG:  shutting down
LOG:  database system is shut down
 done
server stopped

PostgreSQL init process complete; ready for start up.

LOG:  database system was shut down at 2016-09-07 05:34:30 UTC
LOG:  MultiXact member wraparound protections are now enabled
LOG:  autovacuum launcher started
LOG:  database system is ready to accept connections # ここでようやく SQL クエリを受け付けるようになる

ready to accept connections が出る前に SQL クエリを流し込もうとすると、「サーバが見つからないぞ」と怒られることになります。 自分は Docker Compose で PostgreSQL コンテナとアプリケーションコンテナを同時に立たせて何かすることが多いです。が、Docker Compose は起動タイムラグなぞ考慮しないので、続けざまにアプリケーションコンテナを起動すると接続失敗でコンテナが死ぬことが多々ありました。

$ docker-compose up -d db
Creating pq2gorm_db_1

$ docker-compose exec db psql -U postgres -d test 'select * from users;'
psql: warning: extra command-line argument "select * from users;" ignored
psql: could not connect to server: No such file or directory
        Is the server running locally and accepting
        connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?

これでは困るので、ping っぽいことをして外部から PostgreSQL サーバが通信受付状態になっているかどうか確認するすべがないか探しました。しかし、標準機能としては備わっていなかったので若干泥臭い方法をとることにしました。

ping っぽいことをする

psql コマンドでダミークエリを投げて、終了ステータスをチェックすれば良いです。以上です。

$ psql -c 'select 1;'  2>&1 > /dev/null
$ echo $?
#
# 0:    PostgreSQL サーバが起動している
# 0以外: PostgreSQL サーバが起動していない、または起動しきっていない
#

リトライ機構を入れて実用的にする

実際には PostgreSQL につながらなかったら即終了というのも不便なので、リトライ機構を入れるのが普通だと思います。以下は、「5秒待って接続確認する」を最大5回まで繰り返すスクリプトです。5回試してつながらなかったら失敗とみなします。

for i in `seq 1 5`; do
  echo "Wait for 5 seconds..."
  sleep 5

  psql -c 'select 1;' 2>&1 > /dev/null

  if [[ $? -eq 0 ]]; then
    echo "Connection established."
    exit 0
  fi
done

echo "Failed to connect to database."
exit 1

このスクリプトを、SQL クエリを流し込む前段階に仕込んでおけば安心です。

REF