実家に設置してあるサーバがここのところ妙に挙動があやしく、いろいろ調べてみた結果どうもメモリがあやしい、という結論に至りました。しかしそのためだけに新幹線で名古屋まで帰ることも出来ず、しかも今ちょっと入院中なので、リモートで出来る限りのことをしてみました。
まずはsoftware watchdogの導入です。これは/dev/watchdogというデバイスをつくり、定期的に書き込みがあるかチェックして、一定時間(デフォルトは60秒)書き込みがなかったら再起動するというものです。チェックをするためのソフトウェアがDebianにはwatchdogという名前のパッケージであります。インストール時にdebconfでいくつか質問されます。私の設定は以下になります。
# debconf-show watchdog * watchdog/restart: false * watchdog/module: softdog * watchdog/run: true
moduleは利用するwatchdogドライバのモジュール名で、software watchdogはsoftdogを指定します。watchdogデーモンが起動するときにこれがinsmodされます。runは自動起動するかどうかの設定、restartはアップグレード時に再起動をさせるかさせないかを指定します。下手に再起動させると、kernelがwatchdogがとまったと誤認識することがあるので、falseのほうが安全です。
次に/etc/watchdog.confを編集します。デフォルトではコメントアウトされているwatchdog-deviceの行を有効にします。
watchdog-device = /dev/watchdog
これで何かあってシステムがハングすると、再起動するようになります。ただし、ソフトウェア実装なので確実ではありません。
しかしそもそも不安定な原因がメモリにあるので、そこをなんとかしたいところです。昔はbadramというパッチがあって、問題のあるメモリ領域を手動で指定して使わないようにさせる、という方法があったのですが、今はもっといい方法があります。
Linux 2.6.26から導入されたkernel組み込みmemtestです。起動パラメータにmemtest=試行回数を指定することで、メモリのエラーをチェックしエラー領域を使わないよう動作します。
残念ながら、Debianデフォルトのカーネルでは有効になっていないので、
CONFIG_MEMTEST=yを.configに追加して自分でカーネルの再構築をする必要があります(make-kpkgを利用)
自作したカーネルパッケージをインストールしたら、カーネルパラメータを追加してやる必要があります。/etc/default/grubを編集します。
GRUB_CMDLINE_LINUX="memtest=32"
GRUB_CMDLINE_LINUXにmemtest=数値を指定して、テスト回数を指定してやります。この例では32回テストします。テストを増やせばエラーを発見する確立が高まりますが、当然起動には時間がかかります。手持ちのノートPCで試しに255を指定したところ、数分待っても終わる様子がないので完走させる前に止めてしまいました。
最後にupdate-grubを実行して、このパラメータをgrub.cfgに反映させてから再起動します。カーネルがエラーを発見すれば、dmesgに以下のような出力が出ます。
[ 0.000000] early_memtest: # of tests: 32 [ 0.000000] 0000014000 - 000009d800 pattern 0000000000000000 [ 0.000000] 0000100000 - 0001000000 pattern 0000000000000000 [ 0.000000] 00014ee56c - 00014ef000 pattern 0000000000000000 [ 0.000000] 00014fc15c - 00177df000 pattern 0000000000000000 [ 0.000000] 001803f9ef - 0020000000 pattern 0000000000000000 [ 0.000000] 0020200000 - 00377fe000 pattern 0000000000000000 [ 0.000000] 0000014000 - 000009d800 pattern ffffffffffffffff [ 0.000000] 0000100000 - 0001000000 pattern ffffffffffffffff [ 0.000000] 00014ee56c - 00014ef000 pattern ffffffffffffffff [ 0.000000] 00014fc15c - 00177df000 pattern ffffffffffffffff [ 0.000000] 001803f9ef - 0020000000 pattern ffffffffffffffff [ 0.000000] 0020200000 - 00377fe000 pattern ffffffffffffffff [ 0.000000] 0000014000 - 000009d800 pattern 5555555555555555 [ 0.000000] 0000100000 - 0001000000 pattern 5555555555555555 [ 0.000000] 00014ee56c - 00014ef000 pattern 5555555555555555 [ 0.000000] 00014fc15c - 00177df000 pattern 5555555555555555 [ 0.000000] 001803f9ef - 0020000000 pattern 5555555555555555 [ 0.000000] 0020200000 - 00377fe000 pattern 5555555555555555 (以下略)
これで今のところ問題は起きていません。しかしこんな状態で利用し続けるのも問題なので、可能であればECCメモリーにでも乗せかえたいところです。