作ろうと思ったきっかけ
データベース上でデータ不整合が発生する現象が発生した。
AというテーブルのBカラムの集計値はCというテーブルのDカラムと一致しなければならないのに、何故か一致しない。
どこかで不整合が発生する仕組みになってしまったのだろうが、原因が特定できない。
発生した日のログを見ようと思ったが、発生した日すらわからない。
このシステム稼働してもう何年だっけ?という手詰まりなので、
「今までの事はさておき、これから発生したとして、発生した日がわかればログも追いやすいだろう。チェックバッチを作って毎日チェックしよう」という悲しいモチベーションで作る事になった。
check.shをとりあえず作ってみる
ネーミングセンスの悪さは否めない。
先に言っておくと、下の記述は良くない。
#!/bin/bash
# 集計値と異なる場合にメールを送信するsh
# メール送信時に送信時刻を記載するためだけのもの
NOW_TIME=`date +"%Y-%m-%d %H:%M:%S"`
# 送信先メールアドレス
ADMIN="hoge@hogehoge.com"
# SQLファイルの指定
# 簡単ならば直接記述しても良いけれども、ボチボチ修正も入りそうなので
# 外からファイルを読み込む事にする。
SQL_FILE_NAME=diff_check.sql
# このSQLは「count (*)」とかにしておいて、差分が発生した時だけ0以外の
# 値が取得できるものとする。
# MYSQLの設定
DB_USER=hoge
DB_PASSWORD=fuga
DB_NAME=example
COUNT=`cat "$SQL_FILE_NAME" | mysql -u "$DB_USER" -p"$DB_PASSWORD" "$DB_NAME" -N 2>&1`
# ほとんどの場合は何かしらワーニングがついてくると思うのですが…
echo $COUNT
if [ $COUNT -ne 0 ] ; then
echo "$NOW_TIME error" |mail -s "error" $ADMIN
echo "NG"
else
echo "OK"
fi
check_ng.sh: 25 行: [: 引数が多すぎます
とか言われます。
echo $COUNT の中身が「mysql: [Warning] Using a password on the command line interface can be insecure. 0」とかなってるからしょうがないです。
最初は「mysql: [Warning] Using a password on the command line interface can be insecure. 」を削れば良いかと思いました。
COUNT=${COUNT#"mysql: [Warning] Using a password on the command line interface can be insecure. "}
とか。
でもこのワーニング文言、実は環境ごとに微妙に違うようで、この実装だと他の案件で流用できない。それもどうかと思うけれど、何もかもがあまりよくない。
そもそもの話なのだけれども、DB_PASSWORDという変数がもはやおかしい。
https://dev.mysql.com/doc/refman/5.6/ja/environment-variables.html
を見ると
MYSQL_PWDという環境変数がある。これを使えばいい。
※やっぱりセキュアではないんだけれども。
「mysqld に接続する際のデフォルトのパスワード。これを使用することはセキュアではありません。」と書いてある。
本番稼働しているMYSQLに対して、クリティカルな異常でも何でもない監視用バッチの為にcnfを弄って対応する事も難しい。許可が降りない。
どうせ上の例でもパスワードをハードコーディングしていてセキュアでもなんでもないので、今更セキュアを気にしてもしょうがないと割り切る。
#!/bin/bash
# 集計値と異なる場合にメールを送信するsh
# メール送信時に送信時刻を記載するためだけのもの
NOW_TIME=`date +"%Y-%m-%d %H:%M:%S"`
# 送信先メールアドレス
ADMIN="hoge@hogehoge.com"
# SQLファイルの指定
# 簡単ならば直接記述しても良いけれども、ボチボチ修正も入りそうなので
# 外からファイルを読み込む事にする。
SQL_FILE_NAME=diff_check.sql
# MYSQLの設定
DB_USER=hoge
DB_NAME=example
# -pの部分はごっそり消していい。
COUNT=`cat "$SQL_FILE_NAME" | MYSQL_PWD=fuga mysql -u "$DB_USER" "$DB_NAME" -N 2>&1`
# これで件数だけ取得できる
echo $COUNT
if [ $COUNT -ne 0 ] ; then
echo "$NOW_TIME error" |mail -s "error" $ADMIN
echo "NG"
else
echo "OK"
fi
ちなみに、
MYSQL_PWD=fuga
COUNT=`cat "$SQL_FILE_NAME" | mysql -u "$DB_USER" "$DB_NAME" -N 2>&1`
ではダメです。
COUNT=`cat "$SQL_FILE_NAME" | MYSQL_PWD=fuga mysql -u "$DB_USER" "$DB_NAME" -N 2>&1`
こうでないと、うごかない。
cronの設定
あとは、cronで設定するだけ。
00 6 * * * sh /home/hoge/batch/check.sh > /home/hoge/batchlog/check_`date +\%Y-\%m-\%d`.log