アカウント共有型のレンタルサーバならサーバが落ちても、管理者の方が監視してくれていて、再起動なり修理なりしてくれますが、専用サーバやVPSだと、ハード故障以外の管理は基本的に自分でやらなければなりません。
本格的に監視し、ダウンタイムを短くしたいならば、HAクラスタリングや監視ツールなどを入れておく方法が有効ですが、個人でそこまで本格的な物はいらない場合の簡易サーバ監視方法をご紹介します。
今回主に使用する機能は、
- カーネル異常寺の再起動
- サーバのポート定期監視
- watchdog(softdog) によるサーバ高負荷・無応答寺の再起動
の3つです。もちろん全ての故障は救えないので、ご了承ください。
カーネル異常時の再起動
まずは、カーネル異常時にサーバを自動起動させる設定を行います。これは、カーネルパニックや Ooops時に自動再起動する仕組みを設定します。
設定方法はいたって簡単。以下のようにprocのパラメータを変更してあげます。
echo 60 > /proc/sys/kernel/panic echo 1 > /proc/sys/kernel/panic_on_oops
上記の場合、カーネルパニックやOops時発生60秒後に、再起動がかかります。Ooopsは除外したい場合は2行目の設定を行わないでください。この設定はサーバ再起動後元に戻ってしまいますので、起動時に自動的に有効にしたい場合は /etc/sysctl.conf に設定を書いてあげます。
kernel.panic = 60 kernel.panic_on_oops = 1
サーバのポート定期監視
次はサーバのポート監視です。ポート監視には、"nc" というコマンドを使います。例えば、Apacheを監視したいならば、80番ポートを定期的にスクリプトで監視し、異常はhttpサーバを再起動してあげます。
・スクリプト例 (/root/check_server.sh)
#!/bin/bash nc -z localhost 80 > /dev/null if [ $? != 0 ]; then echo "Restarting httpd" /etc/init.d/httpd restart echo "done $?" fi
今回はncでのポート監視でしたが、もっと監視制度を上げたいならば、wgetを使うのもありだと思います。 これを、定期的にcrond で動かしてあげます。今回は5分間隔
# crontab -e */5 * * * * /root/check_server.sh
これでポート監視設置完了です。異常時は、デフォルトだとスクリプト内のechoの文字列などは、rootにメールで送られるはずです。よって、これを外部にメールで知らせたい場合は、メールのエイリアスを送信先のメールに書き換えてあげます。
# vi /etc/aliases ~ 省略 ~ root: abcd@・・・・ ← root宛をabcd@・・・宛に送る
# newaliases ← 設定反映
メールサーバも落ちていると、メール送信できないので、ついでに、メールサーバのポートも監視してあげます。
・スクリプト例 : 25番ポート監視追加
#!/bin/bash nc -z localhost 80 > /dev/null if [ $? != 0 ]; then echo "Restarting httpd" /etc/init.d/httpd restart echo "done $?" fi nc -z localhost 25 > /dev/null if [ $? != 0 ]; then echo "Restarting Postfix" /etc/init.d/postfix restart echo "done $?" fi
以上で、ポート監視関連の作業はおしまい。
次ページは、watchdog(softdog)の設定です。
watchdog(softdog) によるサーバ高負荷・無応答寺の再起動
最後はsoftdogの設定です。
今まで書いたスクリプトはあくまでcronが動いているのが前提です。しかし、実際にはcronがエラーで動かなくなる可能性もありますし、他のプロセスがCPUを食いつぶして、動けない可能性もあります。こういう時に役に立つのがwatchdogと呼ばれる物です。watchdogはwatchdogタイマーというのをセットし、このタイマーを定期的にリセットできないとサーバを再起動させる機能です。
ハードウェアのwatchdogを使う方が、OSが異常になった場合も動くので信頼性が高いのですが、今回はソフトウェアベースのsoftdogを使います。
まずはwatchdogのモジュールを起動時に自動ロードする設定を書きます。
# vi /etc/modprobe.conf ~ 以下を追記 ~ alias char-major-10-130 softdog options softdog soft_margin=1800
上記設定では、1800秒、つまり30分間タイマーをリセットできないと再起動されます。 ※この設定を書いただけでは、まだタイマーはセットされていません。
次に定期的にタイマーをリセットする処理を、スクリプトに埋め込みます。
・スクリプト例 : watchdogリセットを追加
#!/bin/bash
nc -z localhost 80 > /dev/null
if [ $? != 0 ]; then
echo "Restarting httpd"
/etc/init.d/httpd restart
echo "done $?"
fi
nc -z localhost 25 > /dev/null
if [ $? != 0 ]; then
echo "Restarting Postfix"
/etc/init.d/postfix restart
echo "done $?"
fi
echo "a" > /dev/watchdog
上記のように、/dev/watchdog に "V" 以外の文字列を定期的に書き込むだけです。
最後にwatchtogモジュールをロードします。
# modprobe softdog
これにより、タイマーが起動します。以下のようなログが出力されます。1800秒でセットされているのもわかります。
# cat /var/log/messages
May 10 11:00:02 server1 kernel: Software Watchdog Timer: 0.07 initialized. soft_noboot=0 soft_margin=1800 sec (nowayout= 0)
スクリプトが定期的にcronで実行されていない場合は、30分後に再起動するのでご注意ください。スクリプトが正常に動いている時は、
kernel: SoftDog: Unexpected close, not stopping watchdog!
というログがリセットする度に出力されるようです。(ちょっとうざいな) なお、ソース見たところ、/dev/watchdog に書き込むのではなく、定期的にioctlでWDIOC_KEEPALIVEを使ってリセットしてあげれば、このログは出力されないようです。(未確認) また、設定タイムアウト値はioctlで取得できますが、後何秒で再起動されるかを確認するインタフェースはないようです。
softdo.c 抜粋
switch (cmd) {
default:
return -ENOTTY;
case WDIOC_GETSUPPORT:
return copy_to_user(argp, &ident,
sizeof(ident)) ? -EFAULT : 0;
case WDIOC_GETSTATUS:
case WDIOC_GETBOOTSTATUS:
return put_user(0, p);
case WDIOC_KEEPALIVE:
softdog_keepalive();
return 0;
case WDIOC_SETTIMEOUT:
if (get_user(new_margin, p))
return -EFAULT;
if (softdog_set_heartbeat(new_margin))
return -EINVAL;
softdog_keepalive();
/* Fall */
case WDIOC_GETTIMEOUT:
return put_user(soft_margin, p);
}
softdogの手動停止は、"V" を /dev/watchdog に書き込んであげて、rmmod でモジュールをアンロードします。
# echo "V" > /dev/watchdog # rmmod softdog
アンロード成功すると、watchdogデバイスが消えます。
# ls /dev/watchdog ls: /dev/watchdog: そのようなファイルやディレクトリはありません
以上簡易的なサーバ監視でした。これで少しは楽ができるのではないでしょうか!?