職場のウェブサイト用の情報掲示がうまく機能していない!何でだろ~何でだろ~って思ってサーバにログインしたらmysqldが落ちてるでやんす、ってことでやむなく対応に苦慮する

職場の社長からSkype経由で「うちのサイトのお知らせが表示されていない」っていうんでウェブ見たら確かにお知らせが出ていない。システム上の問題か……いや単にお知らせの表示終了日の設定を今日にしてんじゃね?ぐらいの気持ちで社長に返事したら、どうもそうではないらしい。むー。おまけにシステムにログインができない。これどういうこと……サーバ作業なんて何もしてないつーの。


ということで上野に戻ろうと思ったがものっそい暴風雨で御苑からJR新宿駅まで歩く間に全身びしょ濡れになってしまってこれも上野なんて行く気力ないっすってんでそのまま自宅に帰って作業することにした。
まあ自宅からでも何とか作業ができるだろう、ということでおとなしく帰宅。

まずはAmazon EC2のインスタンスにコマンドラインからSSHでログイン
ps axしたら、案の定MySQLが動いてない。
が、なぜそうなったのかは理由がわからない。

ということで、cat /var/log/mysqldをしてみると……。

[text]
140529 01:41:31 mysqld_safe Number of processes running now: 0
140529 01:41:31 mysqld_safe mysqld restarted
140529 1:41:31 [Note] Plugin ‘FEDERATED’ is disabled.
140529 1:41:32 InnoDB: The InnoDB memory heap is disabled
140529 1:41:32 InnoDB: Mutexes and rw_locks use GCC atomic builtins
140529 1:41:32 InnoDB: Compressed tables use zlib 1.2.5
140529 1:41:32 InnoDB: Using Linux native AIO
140529 1:41:32 InnoDB: Initializing buffer pool, size = 128.0M
InnoDB: mmap(137363456 bytes) failed; errno 12
140529 1:41:32 InnoDB: Completed initialization of buffer pool
140529 1:41:32 InnoDB: Fatal error: cannot allocate memory for the buffer pool
140529 1:41:32 [ERROR] Plugin ‘InnoDB’ init function returned error.
140529 1:41:32 [ERROR] Plugin ‘InnoDB’ registration as a STORAGE ENGINE failed.
140529 1:41:32 [ERROR] Unknown/unsupported storage engine: InnoDB
140529 1:41:32 [ERROR] Aborting

140529 1:41:32 [Note] /usr/libexec/mysqld: Shutdown complete

140529 01:41:32 mysqld_safe mysqld from pid file /var/run/mysqld/mysqld.pid ended
[/text]

メモリか……メモリリークかしら?とか思って一応メッセージをGoogle先生で尋ねてみたら、t1.microではMySQLがよく落ちるなどといってる方もおられる。まあ要するにメモリなんだろうな……。たぶんApacheやらmemcachedやら他のシステムも併用して動かしてるとメモリ不足でバッファ割り当てできなくてMySQLがお陀仏に……ということなんだろうか。ん、じゃあmy.cnfを調整すればいけるんかいな?という予感は忙しさにかまけて脳内から排除排除。次落ちたら考えますかね……。

なんていっても落としてまた手動対応もイヤだったので、スクリプトを書くことにした。
イメージとしては、cronを使ってこんな感じで10分おきに起動させて監視、動いてなかったら起動させるという単純なもの。
まあ実際にはもっとしっかり設計しなければならんと思うのだが、まずは暫定ということで対処することにした。モニタリングも本当はZabbixやCactiなどSNMPも使って対応するのがベターなのだが、「自分が不在でもとりあえず落ちたサービスは再起動させたい」というのが目的だったので、cronで動かすことにした。これも人数の少ない少数精鋭のベンチャー企業だからということなのである。

[shell]
MAILTO="hostmaster@example.co.jp"
SHELL=/bin/sh

*/1 * * * * /root/.cronscripts/monitor-mysql.sh 2>&1 >/dev/null
[/shell]

で、このmonitor-mysql.shはどうしたかというと、まずは.cronscriptsというのをrootのホームディレクトリ(/root)に掘る。

[shell]
cd
mkdir .cronscripts
cd .cronscripts
[/shell]

そこでviなりemacsなりcatなりお好みで、まずはパス関連設定だけを書いたPATH.rcファイルを用意。まあこんなのいちいち用意しなくても、それほど数作らないなら直書きでいいんだけど、とりあえず書いておくことに。

[shell]
PS=/bin/ps
GREP=/bin/grep
AWK=/bin/awk
SED=/bin/sed
WC=/usr/bin/wc
RM=/bin/rm
MV=/bin/mv
MKDIR=/bin/mkdir
RMDIR=/bin/rmdir
CAT=/bin/cat
TEE=/usr/bin/tee
EXPR=/usr/bin/expr
PWD=/bin/pwd
LS=/bin/ls
SERVICE=/sbin/service
SLEEP=/bin/sleep
[/shell]

いよいよmonitor-mysql.shである。このファイルの中でPATH.rcを最初に読み込み、それ以降は各コマンドのフルパスを気にすることなく変数名で指定すればいい。

[shell]
#!/bin/sh
. /root/.cronscripts/PATH.rc

mysqld=$PS ax | $GREP mysqld | $GREP -v grep | $WC -l
mysql_safe=$PS ax | $GREP mysql_safe | $GREP -v grep | $WC -l

if [ $mysqld -eq 0 -a $mysql_safe -eq 0 ]; then
$SERVICE mysqld start
fi
[/shell]

ファイルを保存したらchmod 750 monitor-mysql.shとかすればいい。

まあ本当はserviceコマンドのあとにsleep 1でもかましてから再びps axで確認するというのがベターだとか、やり方をもっと繊細かつ丁寧にするほうが本当は大切なんだけれど、おおまかにこのぐらいでも暫定運用上は問題がないだろう、と思う。

実際にcrontab -eで設定する前に、スクリプトがちゃんと動くかどうかを手動で確認しておく必要がある。

[改訂新版] シェルスクリプト基本リファレンス  --#!/bin/shで、ここまでできる (WEB+DB PRESS plus)覚えて便利 いますぐ使える!シェルスクリプトシンプルレシピ54UNIXシェルスクリプトコマンドブック 第2版詳解 シェルスクリプトUNIXシェルスクリプト マスターピース132ハーシー シェルトッピングチョコレート 205g

コメントを残す

メールアドレスが公開されることはありません。