つれづれなる日記 @ maoo.jp

退屈な日々をより退屈な文章でだらだらと

正確な時刻を求めて

関連
http://d.hatena.ne.jp/maoo/20090902/1251905708

(前書き)

 一般的なコンピューターにおける内部時計の時刻補正に関して、なんだかんだだらだらと書いてみるつもりなのであった。用語説明とか技術の解説などについては面倒だしやらないつもりなので、もしもいろいろとくわしく知りたい方であるなら、たとえばWikipediaにおいて関連するページを参照するなりして調査なさるのがよろしかろう*1。ここでは、少なくともやさしくわかりやすく解説しているなんてことはまったくないので、ええとその、そういう期待はしないように。

コンピューターの時刻はわりとずれる

 今時のパーソナルなコンピューターであれば、ネットワーク経由で時刻を同期するような仕組みを標準で実現しているようなものがほとんどであると思う。具体的には、Internet上のNTPサーバーに*2接続して正確な時刻の情報をいただいて、それを用いて内部時計の時刻を補正するといったような、そういう機構のことだ。最近はスタンドアローン*3稼働するパーソナルコンピューターは少数派だろうから、不正確な時刻設定であるとまずい事態が発生することも昔より考えられるわけで、とりあえず正確さを目指すほうが無難だろうと思う。
 ついでに書けば、市販されているような一般的なコンピュータにおける内部時計の(機械的)精度なんてものは、まずたいしたものではないはずであって、だから一回だけ正確にすればそれで安心ということではなく、継続的に正確さを保つ必要があると考えた方がいい。とはいえ、OSの標準状態にしろ世にあるソフトウェアにしろ、最近のものはとりあえずそういうことができるようになっているのがほとんどだと思う。そんなわけで、NTPサーバーが負荷で苦しまない程度で便利に利用させていただくのがよかろう。

ご家庭用コンピューターとntpd

 自分の部屋にはいろいろなマシンがあるわけだが、ClassicなMacOSで稼働している"Power Mac G4 Cube"ちゃんや仮想マシン環境で動作しているLinuxなOSの環境などなどを別扱いとして除外するなら、"Windows XP"なOSが動作しているDell君と、そしてメインで利用している"MacBook Pro"さんがあるわけだ。この2つの環境においては、今のところどちらも時刻補正のためにはntpdを稼働させている。前者については標準装備が気に入らなかったので自分で導入したのだが、後者は標準装備がそのままそうなっている。
 時刻補正を定期的に行う仕組みはいろいろとあるけれど、ntpdはわりと高級なことをやるデーモン(Daemon)であって*4、ただ定期的に(たとえば何分かに一度というパターンで)時刻補正を繰り返すわけではない。まあそれなりに難しいことを考えてできるだけ時刻を正確にするようにがんばってくれるようなタイプのものであり、当然それだけ処理としては比較的複雑になっていき資源もそれなりに消費するという欠点もあるのだが、とりあえず自分はこういうのが好きなのである。
 好きではあるのだが、パーソナルコンピューターでの稼働では特有の問題が発生してくる。もともとntpdというのは、ネットワークに接続されたままずっと稼働しているサーバーマシン・ワークステーションなどで効率よく機能させるという前提があったように思われるわけで、短い時間で電源をオンにしたりオフにしたりスリープ機能を多用したりというパーソナルコンピューターでよくありそうな利用スタイルには、要するにあまり適していないようなものと想像される。
 自分のコンピューターに限定して考えるなら、Internetに接続した状態でそれなりに継続して稼働させておくという条件についてはクリアされているだろうし、その点で問題はなさそうだ。ただし、"MacBook Pro"さんでそこそこ多用するスリープ機能では、目覚めた瞬間に時刻がずれているという問題が発生していたわけだが*5、それについても最近になってむりやり解決したので、やっぱり問題はないだろう。とりあえず今のところはこの環境を維持していって大丈夫であるように思う。

MacOSでの時刻補正環境を改善する

 もちろんWindowsなOSのほうが便利だとか優れていると思う場面だってあるわけだが、自分は環境としての"Mac OS X"なOSが*6かなり好きだ。「OSの基盤が(これまた自分が好きな)UNIXなOSであるから」という理由もきっと影響している。基本的には相性のようなものなのだろうが、趣味としていじるならこっちのほうがいいなあ…と。ところで余談だが、GUIというか見た目はClassicの頃の*7プラチナアピアランスのほうが今でも好きであったりする。あれはまことに美しかった…。
 さて、この"Mac OS X"については、標準状態でntpdを利用するようになっていることの是非はとりあえずおいといて、しかしntpdの運用方式が洗練されていないとは思う。かなり思う。正直に発言するといろいろな部分で不満だ。面倒なのでやっていないが、元気があるなら開発元に改善要請を文書にして提出したいくらいだ。Leopard(="Mac OS バージョン10.5")になっても、Jaguar(="Mac OS バージョン10.2")の頃からあまり進化していないように思えるんだよなあ。なんとかしてくれないかなあ。
 ぼやいてみたところで、今のところなんともなっていないわけで、不満ならば自分でなんとかするしかないのである。というわけで、自分が利用している"MacBook Pro"の"Mac OS X"バージョン10.5.8環境において、よりエレガントで効率的かつ正確な時刻補正のために自分がいじった部分について、ここに書いておこうと思う。もしかしたら後に自分が"Snow Leopard"(="Mac OS バージョン10.6")に環境を移行させる時にも役立つかもしれないし。いろいろと忘れっぽいから。

スリープ後の目覚めで即座にntpdを再起動

 これについては、最初に関連記事としてリンクしてある場所でもう書いたので、ここでは省略。

ntpdのConfigurationに関する小細工

 「システム環境設定」の「日付と時刻」においては、接続して時刻補正を行うNTPサーバー(のホスト名かIPアドレス)のみを簡単に指定できるようになっている*8。とても親切そうに見えるが、これがいけない。Configurationとして"/private/etc/ntp.conf"に設定できる情報はそんなに単純ではないのだ。複数のNTPサーバーを記述したいし、そしてそれぞれminpollやmaxpollそれにiburstやpreferだって記述したいのだ。なのにGUIで見た目だけむりやりシンプルにして、そういうことをしたい人の邪魔をするなと言いたい。
 では自分でファイルの内容を改変すればいいではないかと思われるかもしれないが、それは不完全かつ危険な行為だ。少なくとも「日付と時刻を自動的に設定」がチェックされている(=ntpdを起動して時刻補正を行う環境になる)「システム環境設定」では、その実行時に「日付と時刻」を表示しただけで*9、理解できる内容のみそのファイルへ即座に出力してから*10ntpdの再起動をするということをしでかしてくれるわけで。せめて内容の改変を行った場合のみでの処理でないと*11、ほとんど暴挙としか思えないんだが…。
 というわけで、対策。ntpdの起動に関してはlaunchdに一任するような機構となっていて*12、"/System/Library/LaunchDaemons/org.ntp.ntpd.plist"での記述により"/usr/libexec/ntpd-wrapper"が実行されるが、その中で指定されている"/private/etc/ntp-restrict.conf"が実行時に参照される。この内容を改変し、"includefile"の指定を自分が独自に作成したもののファイル名にして対応した。さらに、例の"ntp.conf"には「ここの内容は無効だよ」なんてメッセージを書いて勘違いを防止してみたり。あと、できるだけ「日付と時刻」は見ない。
 ちなみに、今のところ自分が利用しているntpdのConfigurationはこんな感じのものであるが*13

server   127.127.1.0                 minpoll  4 maxpoll 17
fudge    127.127.1.0                                       stratum 12

server   ntp??????????.or.jp  iburst minpoll  9 maxpoll 12            prefer

server   ntp??????????.ad.jp  iburst minpoll 10 maxpoll 11            prefer
server   ntp???????????.ad.jp iburst minpoll 10 maxpoll 11            prefer
server   ntp???????????.ad.jp iburst minpoll 10 maxpoll 11            prefer
server   ntp???????????.ad.jp iburst minpoll 10 maxpoll 11            prefer

server   ntp?????.gr.jp       iburst minpoll 10 maxpoll 11
server   ntp??????.gr.jp      iburst minpoll 10 maxpoll 11
server   ntp??????.gr.jp      iburst minpoll 10 maxpoll 11
server   ntp??????.gr.jp      iburst minpoll 10 maxpoll 11

server   ntp?????.jp          iburst minpoll 11 maxpoll 11            prefer
server   ntp????????.go.jp    iburst minpoll 11 maxpoll 11            prefer
server   ntp????????.go.jp    iburst minpoll 11 maxpoll 11            prefer
server   ntp????????.go.jp    iburst minpoll 11 maxpoll 11            prefer
server   ntp????????.go.jp    iburst minpoll 11 maxpoll 11            prefer

そんなに頻繁な接続はしないけどサーバー数の多さでカバーというか、まあそんなポリシーだ。極端に時刻がずれる「スリープ後の目覚め」問題は解決しているし、これで特に問題はないと感じている。それでもなんとなくたまに気になって、またちまちまと改変したりしているけれど。そういう性格なんだな、きっと。
 ところで、もしも利用するべきNTPサーバーを探すということならば、基本的に以下のような条件を満足する

  1. 信頼できる(組織が管理している)
  2. (運営・稼働状況が)安定している
  3. (ネットワーク的に)近い距離にある

ホストであることが望ましい。利用しているISP*14そういうサービスを提供してくれているなら、それをわざわざ無視することもないだろう。あとは、おそらく日本で利用する場合に適しているであろうサービスが、たとえば以下のように

いろいろとあるので、ありがたく活用させていただくのがいいだろうと思う。ついでに、複数の組織かつ複数のサーバーを利用するようにすると、(基本的には)安全性などの面でより望ましいことになるだろう*15

通常時刻同期開始直前の時刻補正

 先にも書いた通りntpdはかなり高級であり、内部でかなり複雑なことをやってくれている。時刻を補正していくにしても、いきなり正確な(少なくとも正確と判断された)時刻にジャンプさせるのではなく、少しずつだんだんとその正確な時刻に近づけていくといった補正の挙動が標準の動作になっている。cronなどの*16動作を考えればこれは非常にありがたくそして必要なものでもあって、もしそうでなくともより望ましい時刻補正方法であろう。
 ただしこの方式には欠点があって、それは「時刻のずれを補正していくには時間がかかる」ということだ。よって、大きなずれを補正するにはたくさんの時間が必要であって、ある程度ずれが大きくなると補正が現実的に不可能となり、極端なずれがある場合では(多くの実装で)おそらくntpdが稼働を拒否することになる。このため、基本的にntpdで通常の時刻同期を開始する直前には、たとえ時刻のジャンプを伴おうとも強制的に正しい時刻に近い状態にまで補正させておく必要がある。
 もちろんこのOSでもその機構は用意されているわけだが、それにはちょっと問題が。標準状態ではそのためにntpdateを利用しているのだが、これは(実は仕様についてはよく確認していないけど)"/private/etc/ntp.conf"を参照するようだ。ntpdの稼働と無関係にしてしまったこのファイルを参照されるのはうれしくないし、別ファイルにあるntpd用の情報をここにいちいちコピーするのも面倒だ。ついでに"ntpdate"は引退が決定しているコマンドであって、使用しないで対応できるならそうしたほうがいいだろう。
 というわけで、ntpdateの

ntpdate -bvs

代用としてntpdを

/usr/sbin/ntpd -c /private/etc/ntp-restrict.conf -n -g -q

みたいに利用する。なんだか話が変ではないかとここで考えたあなたはとても正しいが、ntpdはntpdでも"-q"そして"-g"のオプションをつけたものなのだった。こうすると、ntpdateの通常動作をまねた*17「大急ぎで一気に時刻を強制的に正確にしてから終了する」のような挙動をしてくれる*18。これならConfigurationも通常稼働の場合と共用できるわけで、運用も楽である。というわけで、そのように"/usr/libexec/ntpd-wrapper"の内容を改変した。

ドリフトファイルの運用…はそのままでよかった

 昔の環境では"ntp.drift"は"/var/run/"に位置していて、しかしこのディレクトリーの内容はシステムブート(boot)でいちいちクリアされるようになっていた。というより、そういう運用のためのディレクトリーになぜかこのファイルを保存するようになっていたわけだが、これは明らかな誤りである。ドリフトファイルの内容は、ntpdが稼働していく中でだんだん正確な値に近づいていく(べき)ものであって、(なんらかの理由で異常な値になった場合でもなければ)いちいち破棄すべきではないのだ。
 そんなわけで以前は、このファイルを別の場所に待避させてまた回復させて…なんてことを独自に実現させていたのだが、今のバージョンのOSでは"/var/db/"に保存して勝手に消去はしないようにしたらしい。おお、なんかきちんと改善している部分もあるんだなあと、ちょっとだけ感動したわけだった。だがNTP関連では、ここだけではなくもっといろいろとがんばってほしい。少なくとも一般ユーザーが動作の改善のために(この場で書いた部分とかを)いろいろいじらないといけない状況は、あまりエレガントではない。

パーソナルならもっと楽でありたい

 そんなわけで、とりあえず一連の作業は完了しているわけだが、少なくとも簡単ではなかったような気がするわけであり。なんというか、もうちょっとOSの標準状態でなんとかならないものなのだろうか。少なくともパーソナルコンピューター略してパソコンなんてものであるならば、いちいちこんなことを一般ユーザーにやらせちゃいかんだろうと。もっとも、ほとんどの人にとって正確な時刻の追求なんてことは気にもならないのかもしれないが。いや、気にしたほうがいいと思うんだけどなあ。ブツブツ…。

(余談)

仮想マシンとntpd

 少なくとも以前に自分が試してみた場合においては、仮想マシンのゲストOS上でntpdを動作させることは良い結果にならなかった。ntpdはけっこう複雑な演算なりを行っていそうだが、それにはハードウェアとしてのクロック精度のようなものがかなり必要そうに思え、しかし、ホストOSの負荷なりの事情で仮想マシンについてのハードウェア性能(に相当するもの)すら動的にかなり変化する可能性がありそうな仮想マシン環境では、そのゲストOS上のntpdとしても働きにくいということなのではないだろうか。*19
 そのようなわけで、自分が現在も利用しているゲストOSのLinuxな環境においては、cronで定期的にntpdateを実行することで対応させているわけだ*20。ところで、仮想マシン環境そのものでも(仮想マシンへの)それなりの時刻補正機能が用意されていて、今はそれも利用しているのだが、このように複数の補正機構を併用する場合ならなおさら(デーモンとして働かせる)ntpdは適さないことだろう。なんにしても、ntpdはデリケートでありシビアな動作をするようなソフトウェアなのだと思う。

*1:そのほうがきっと正確でわかりやすいだろうし。

*2:参考 Network Time Protocol - Wikipedia

*3:参考 スタンドアローン - Wikipedia

*4:参考 デーモン (ソフトウェア) - Wikipedia

*5:これは、先代のiBookさんでも同様の現象が発生していた。まあなんというか、いきなり時間を急激に移動させられたntpdの気持ちも、ちょっとわかるような気がしないでもない。

*6:参考 macOS - Wikipedia

*7:参考 Mac OS - Wikipedia

*8:初期状態では、Appleさんのところのサーバーに接続するようになっている。

*9:正確には、表示した状態から「別の表示に変更する」か「終了する」ことによって…ということだと思われる。

*10:つまり、「システム環境設定」から「日付と時刻」のGUIを用いて設定できるようなレベルの内容でないならば、当該ファイルについて手作業で編集した結果はまず破壊されることになってしまう。

*11:実際には、ntpdの再起動はlaunchdが"/System/Library/LaunchDaemons/org.ntp.ntpd.plist"の内容に従い"/private/etc/ntp.conf"の更新を感知し行うものであり、その挙動に問題があるとは思われない。問題なのは、ユーザーが内容の改変もしていないのに律儀に"/private/etc/ntp.conf"に出力を行ってくれる「システム環境設定」の挙動だ。

*12:昔のバージョンのOSだと、ntpdの起動・再起動・停止にはSystemStarterから"/System/Library/StartupItems/NetworkTime/NetworkTime"のシェルスクリプト(Shell Script)を利用する環境になっていたので、自分はその内容を改変して強制的にファイルの上書きをするようにしていた。

*13:こういう場所で公開するのもいろいろな意味でご迷惑かもしれないので、外部サーバー名の一部は伏せ字('?')にしてある。

*14:参考 インターネットサービスプロバイダ - Wikipedia

*15:あるサーバーがダウンしていたりある組織方面へのネットワークで障害があっても、他でカバーできるようになる。また、不正な時刻のサーバーが一部にあったとしても、他のサーバーの情報と比較ができる環境であれば、自動的に無視されることになる可能性が高くなる。

*16:参考 crontab - Wikipedia

*17:ntpdateでも、オプションによって「時刻のずれをだんだん補正していく」「時刻のずれをすぐに補正する」を選ぶことができるわけだが。

*18:つまり通常のntpdの挙動と違い、たとえ非常識に大きな時刻のずれがある状態で実行しようともまったく平気となるわけだ。

*19:ここらへんで利用している用語が厳密に正しいものかどうか、実はあまり自信がない。自分としては、「物理マシン」で動作する「ホストOS」があり・そこに「仮想マシン環境」が構築され・その上に「仮想マシン」とそこで動作する「ゲストOS」がある…というイメージなので、そのつもりで読まれると意味がわかるだろう。

*20:前述のとおりオプション指定でntpdでも同じことはできる。だが実行時の負荷その他のコストを考えると、定期的に実行するならばこちらのほうがより望ましいように思える。