引き続き玄箱(初代)の話です。
ひととおりアップグレードも終わり最新版になったということで(カーネルは古いままですがこれは後日)、今回は玄箱をまともに動かすための設定を。
ntpdateを導入して自動時刻合わせ
玄箱の内蔵時計はハードウェアのバグ(回路設計ミス)のためかなり不正確とのこと。(cf.
Revulo's Laboratory等)
ただ、今回使わせてもらったDebian化キットのカーネルはクロック補正の処理が入っていて、1日に1~2秒ずれる程度まで改善されているそうです。
というわけで、玄箱の時刻合わせに関しては、検索すると「adjtimexとntpを併用」という話がよく見つかりますが、この程度のズレならntpだけでも大丈夫じゃないかと。
まずインストールします。
# aptitude install ntpdate
設定ファイルは /etc/default/ntpdate です。ちょっと修正します。
NTPDATE_USE_NTP_CONF=no
NTPSERVERS="ntp1.jst.mfeed.ad.jp ntp2.jst.mfeed.ad.jp ntp3.jst.mfeed.ad.jp"
NTPOPTIONS=""
2番目のNTPSERVERS で、日本で使う場合に適したNTPサーバーを指定します。スペース区切りで複数のサーバーを指定できます。
NTPサーバーを指定したので、1番目の「ntp.confを使うか」というオプションはnoでいいです。
3番目のオプション指定部分ですが、ここに何も指定しないのが今回の肝です。
検索してみると、ここに -b や -s オプションを指定している人が多いようです。
-b オプションは強制的にstepモードにするオプション。
マニュアルを読むと、ntpdateの時刻補正の仕方には2種類あるようです。
stepモード:
標準では、NTPサーバに問い合わせて差が0.5秒より大きかったとき。(-bオプションを指定すると、ズレの大きさに関わらずstepモード)
一気に正しい時刻に設定する。
slewモード:
標準では、NTPサーバとの差が0.5秒未満以内のとき。(-Bオプションを指定すると、ズレの大きさに関わらずslewモード)
1秒の長さを微妙に伸ばしたり縮めたりして、じわじわとつじつまを合わせていく。
(※ntpdateのmanには「0.5秒」と「128ミリ秒」が混在していて、実はどっちが正しいかよくわかりません…。あと細かいことですが、「0.5秒より大きい」「0.5秒より小さい」場合しか書かれておらず、0.5秒ちょうどの場合がどっちなのかも不明。どっちでもいいですが)
slewモードは何でそんな妙なことをやるかというと、いきなり時計が未来や過去に飛んだりすると、ソフトによっては困ったことになるかもしれないからです。
たとえば「10時丁度になったらメールを送る」というタイマーが仕掛けてあったとしましょう。で、9:59に時刻合わせをしたら2分遅れていたことが判明したと。それでいきなり10:01に時計を直してしまうと、10:00という時刻は訪れなかったことになり、そのメールは送信されないかもしれない。そこで、時計の針の回転をちょっと速めることで、じわじわと差を詰めていくという方法が用意されているのです。
というわけで、内蔵時計の誤差が激しかった玄箱の場合は、一時間に1回くらいstepモードで調整しないと追いつかなかったのかもしれませんが、カーネルで補正されてそんなにズレなくなったのなら「状況によってslewモードとstepモードを使い分ける」というデフォルトのほうが良いかと。
もう一つ、-sオプションというのは、ログを標準出力ではなくsyslogに出す設定。これはここで設定すべきではないのです。
Debianのntpdateの起動タイミングは、2つのパターンが想定されています。
1. マシンを起動したときに実行(正確にはネットワークが利用可能になった直後)
2. 手動で実行
このどちらの場合にも共通なオプションのみを、/etc/default/ntpdate に書くことになっています。
1. の起動時に実行されるスクリプトは /etc/network/if-up.d/ntpdate です。このスクリプトは /usr/sbin/ntpdate-debian というスクリプトを「-b -s」オプションを付けて呼ぶようになっています。ntpdate-debian は、/etc/default/ntpdate で設定された項目を読んで ntpdate を実行します。
そのため、/etc/default/ntpdate で -s を指定しないでおけば、2.の「手動で実行」の場合は、ntpdate-debian を実行するだけで標準出力に結果が表示されるようになるのです。
ntpdateをcronで一日一回自動実行
さて、ではこの仕組みを生かした上で、一日一回cronで回すようにしてみましょう。
デイリーで回したいものは /etc/cron.daily/ の下にスクリプトを置きます。さっきの /etc/network/if-up.d/ntpdate を参考にして /etc/cron.daily/ntpdate というスクリプトを作ります。
#!/bin/sh
if [ ! -x /usr/sbin/ntpdate-debian ]; then
exit 0
fi
/usr/sbin/ntpdate-debian -s
-s オプションだけ付けて ntpdate-debian を呼びます。-b オプションは付けないので、ntpdateの標準の作法通り、つまりズレが0.5秒未満ならslewモード、0.5秒以上ならstepモードで時刻を修正します。
…という設定をしたのが実は1週間前。実際の稼働状況を見てみます。
# grep ntpdate /var/log/daemon.log*
Aug 18 06:27:18 kurobako ntpdate[1493]: adjust time server 210.173.160.57 offset 0.293154 sec
Aug 19 06:26:53 kurobako ntpdate[1426]: adjust time server 210.173.160.87 offset 0.107805 sec
Aug 20 06:25:34 kurobako ntpdate[1306]: adjust time server 210.173.160.87 offset 0.269930 sec
Aug 21 06:25:45 kurobako ntpdate[1572]: step time server 210.173.160.27 offset 1.098734 sec
Aug 22 06:25:35 kurobako ntpdate[2081]: step time server 210.173.160.57 offset 1.158114 sec
Aug 23 06:25:37 kurobako ntpdate[2199]: step time server 210.173.160.27 offset 1.145981 sec
Aug 24 06:25:42 kurobako ntpdate[3309]: adjust time server 210.173.160.27 offset 0.062564 sec
「adjust」とあるのがslewモードの日、「step」がstepモードの日です。0.06秒だったり1.15秒だったり、18倍も開きがあってなんだか極端ですが、ま、悪くないんじゃないでしょうか。