一週間ほど休暇で自宅を留守にしていたら、
運悪くちょうど半ばあたりで自宅の Linux サーバ
(二台ある GCD ゲートウェイのうちの片方) がハングしてしまった。
きっかけは毎晩ハードディスの内容をバックアップするために動かしている
rsync だったので、
メモリ不足 ? かなにかの原因でカーネルのバグを引き当ててしまったのか?
安定版でないカーネルを使っていて再びハングする危険もあるので、
早急にバージョンアップが必要なのだが、
その前に新しいカーネルで GV-MVP/RX2W を動かせるようにしないと... (^^;)
# ぱ研を参考にさせてもらっています (_O_)
GCD のゲートウェイは VRRP で二重化してあるので、
片方がハングしても問題無いのではあるが、
手動リセットするまでハングしっぱなしというのでは、
留守の期間が長いと二台ともハングする可能性を否定できない。
# UUCP スプールなど二重化されていないものもあるので、
全く問題が無いというわけでもない
そこでハングしてもなるべく自動的に復帰できるように
ウォッチドッグ タイマ (Watchdog Timer) を仕掛けることにした。
つまり一定期間内にタイマがリセットされなければ、
ハングしたと見なして問答無用でカーネルを落とす仕掛けである。
ソフトウェアにどんなトラブルが起きても確実に再起動を行なわせるには、
ハードウェアで物理的にリセット スイッチを押すハードウェアを用いるのが
一番であるが、まずはお手軽にソフトウェア版を利用してみることにした。
ソフトウェアによるウォッチドッグ タイマの場合、
カーネル パニックが起きると当然機能しなくなるわけだから、
パニック時は自動的に再起動するように設定しておく必要がある。
rc.local 等で、
echo 60 > /proc/sys/kernel/panic
echo 1 > /proc/sys/kernel/panic_on_oops
を行なっておけば、パニック時は 60秒で再起動するようになる。
次に、ソフトウェア版ウォッチドッグ モジュール (softdog) をインストールする。
softdog.ko を /lib/modules/current 以下に置き、
/etc/modprobe.conf に以下の行を追加するだけ。
alias char-major-10-130 softdog
options softdog soft_margin=3600
ウォッチドッグ タイマというと、
普通は 60秒くらいに設定しておくものだとは思うが、
自宅サーバの場合、一時間くらいハング状態が続いてもそんなに困らない ;) のと、
あまりタイマの間隔が短すぎると、不用意に再起動してしまう恐れもあるので、
3600秒 (一時間) に設定している。
つまり一時間以内にタイマをリセットしないと、自動再起動が行なわれる。
後は適当な方法で、
/dev/watchdog に適当な文字 (ただし「V」を除く) を書込むだけである。
例えば、定期的に実行される sh スクリプトに、
echo "@" > /dev/watchdog
という行を追加しておくだけでよい。
Linux カーネルのドキュメント:
linux/Documentation/watchdog/watchdog.txt
には、
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int main(int argc, const char *argv[])
{
int fd=open("/dev/watchdog",O_WRONLY);
if(fd==-1)
{
perror("watchdog");
exit(1);
}
while(1)
{
write(fd,"\0",1);
fsync(fd);
sleep(10);
}
}
というサンプルが載っているが、タイマをリセットするプログラムを
動かしっぱなしにする方法だと、
ハングの仕方によってはこのプログラムが動き続ける
(つまり自動再起動が行なわれない) 危険がある。
私の自宅サーバの場合は、たとえカーネルが生きていても、
リモートから ssh ログイン出来ない状態なら使い物にならないわけで、
外部から ssh ログイン出来る場合のみタイマのリセットが行なわれるようにした。
つまり、外部から
ssh server "echo @ > /dev/watchdog"
に相当することを定期的に (一時間以内の間隔で) 行なえばよい。
この場合、/dev/watchdog に文字を出力する都度、
/dev/watchdog をクローズすることになり、
SoftDog: Unexpected close, not stopping watchdog!
というメッセージが syslog に出力されるので、
果たしてきちんとタイマのリセットが行なわれているのか不安になるが、
softdog モジュールのソースを見ると、
このメッセージが出力される場合は常に
「softdog_keepalive()」呼び出しが行なわれているので問題ない。