MySQL、 PostgreSQLのシンプルな死活監視
はじめに
Amazon RDSなどマネージドなサービスを利用する場合は基本的にCloudWatchなどリソースの状態を監視できるサービスの提供がされている。とても便利。
が、今回インスタンスに直接DBを乗せる必要があり上記のようなサービスの利用はせず、自前で簡単ではあるが死活監視をしておきたいと思い調べてみた。RDBMSとして広く利用されているMySQL、PostgreSQLについてシンプルなスクリプトを書きたい。ひとまず手元で動くか試してみる。
死活監視の要件としては以下
- RDBのデーモンが走っていることを確認する
- 監視結果が違う場合は全て異常と見なす
- 異常である時Slack・メールなどに通知する
- SlackのWebhookを使うことにする
- ローカルから監視する
要件を満たすシェルスクリプトを用意し、cronで定期実行という運用を想定している。
MySQLの監視スクリプト
mysqladmin ping
コマンドを実行し、"mysqld is alive"が返ってくる場合のみ正常と見なす。
#!/bin/sh
# 標準出力、標準エラー出力しない command > /dev/null 2>&1
IS_ALIVE="mysqld is alive"
RESULT=`mysqladmin --defaults-extra-file=filepath ping 2>&1`
# "mysqld is alive"以外はslackに通知
if [ "$IS_ALIVE" != "$RESULT" ]; then
curl=`cat <<EOS
curl
-X POST
https://hooks.slack.com/services/xxx
-H 'Content-Type: application/json'
--data '{"text": "<!channel> mysqld is dead"}'
EOS`
eval $curl > /dev/null 2>&1
fi
※シェルスクリプトで直接パスワードを指定すると警告が出てしまうので、設定ファイルを作成し接続オプションでそのファイルを指定する。(コマンド実行履歴には*.shとなるため、historyコマンドなどではパスワードが露呈しないが。)
// 何かしらのエディタで設定ファイルを作成
$ vim ~/.mysql.access.conf
[client]
user = username
password = passwd
host = hostname
port = portnumber
$ chmod 600 .mysql.access.conf
$ mysqladmin --defaults-extra-file=~/.mysql.access.conf ping
mysqld is alive
シェルスクリプトの実行結果を標準出力したくなかったので、闇に葬った。。。2>&1
がミソ
実行結果を出さないだけなら以下。が、標準エラー出力の方は出力される
PostgreSQLの監視スクリプト
PostgreSQLの方もほぼ同じ要領でスクリプトを書いてみる。
PostgreSQL9.3から導入されたpg_isready
コマンドを使用する。
#!/bin/sh
IS_ALIVE="accepting connections"
RESULT=`pg_isready -h hostname -p portnumber 2>&1`
# "accepting connections"が含まれてない場合、slackに通知
if [ ! `echo "$RESULT" | grep "$IS_ALIVE"` ]; then
curl=`cat <<EOS
curl
-X POST
https://hooks.slack.com/services/xxx
-H 'Content-Type: application/json'
--data '{"text": "<!channel> postgres is dead"}'
EOS`
eval $curl > /dev/null 2>&1
fi
おわりに
今回はデーモンが動いてるかの確認をして死活監視をした。こだわればキリがなさそうなので、ひとまずこれで異常は検知できるとして当初の要件は満たすことができたとする。
もっとシンプルでいいならping打ってDBサーバーが落ちてないか確認とか、ps | grep
でプロセス名で検索するとか。
異常がないか検知するという意味で、SQLを実行するのも良いなと思った。SELECT now();
など。
一応、GitHubにサンプルを載せておいた。
ほぼ初めてシェルスクリプトを書いた。自分で書くと色々学べるなと再認識。少しづつでも勉強頑張ろう。
今回はRDBのデーモンのみ対応したが、Webサーバーのデーモンなど同じ要領で追加しておこうと思う。(ロードバランサを入れてない構成とかで使えるかも?)
おまけ(shebangについて)
シェルスクリプトの1行目に書く"#!"の部分をシバン、シェバンと呼び、これから使用するインタプリタを指定する役目がある。当初これを#!/bin/sh
としていたが、死活監視とは別件でシェルスクリプトを書くことになり色々調べていたらある記事で#!/usr/bin/env bash
というような書き方をしており、「なんだこの書き方は?」となり調べてみることにした。
例に示した書き方はenvコマンドを利用してPATHに定義されているパスの中から定義順にbashが見つかれば、最初にbashの存在するパスが適用されるという感じらしい、なるほど。また、bashがデフォルトシェルの環境で#!/bin/sh
を指定するとPOSIX(Wikipedia)機能とやらが有効になり、できるだけshっぽく振る舞ってくれるらしい。つまり、bashで動く前提で書いてるスクリプトが期待通りの挙動をしないことがある。プログラム特有の機能を使う際は指定するのが良い。
対象インタプリタの絶対パスを知っているなら/bin/bash
といった指定で問題はない。その代わり、存在しない場合エラーが起きる。そのため、#!/usr/bin/env bash
とすることでヒットさせやすくするという具合のようだ。
shebangについては以下リンクを参考にしました。
参考URL
MySQL
PostgreSQL
シェルスクリプトもろもろ
Discussion