Linux
systemd
ntp
timedatectl

systemd環境におけるハードウェアクロック調整

切迫した事情があったわけではありませんが、気になって調べたので結果をまとめておきます。
テスト環境はopenSUSE Tumbleweedですが、まぁsystemd環境では大概同じでしょう。

まずはsystemdに尋ねる

$ timedatectl statusして、得られる出力はこんな感じになります。

bash
$ timedatectl status
      Local time: 火 2017-11-07 18:29:15 JST
  Universal time: 火 2017-11-07 09:29:15 UTC
        RTC time: 火 2017-11-07 18:29:15
       Time zone: Asia/Tokyo (JST, +0900)
 Network time on: no
NTP synchronized: yes
 RTC in local TZ: no
$ 

ただし上例は一点を除いて全く正常で、その点も例外事項で異常ではありません。
で、以下の箇所を確認。

  1. NTPを使う設定になっているのにNTP synchronized: noになっていないか
  2. 特別な理由がないのにRTC in local TZ: yesになっていないか

NTPが機能するようにする

お使いのディストリビューションでどのNTPデーモンを使っているかに注意して、使用中のNTPデーモンの設定を確認しましょう。
systemd-timesyncd(8)、ntpd(1)、chrony(1)、openntpd1など色々な実装がありますが、Network time on: yesとなるのはsystemd-timesyncdがenabledな場合に限られますので多くの環境では当該項目はあてにならないことを頭に入れておいてください。先ほどの例では、ntpd(1)により時刻が同期されていたためnoながらNTP synchronized: yesになっています。
ここでは各実装における設定ファイルの書き方には触れません。

RTCがローカル時刻に設定されている場合

Windows環境を上書きしてインストールした環境などでよくなっていますが、Linuxにおいてこの状態は好ましくありません。Windowsとのデュアルブート仕様である2などといった特別な事情がなければ、コマンド一発# timedatectl set-local-rtc 0で直してしまいましょう。

なお、この操作により/etc/adjtimeが書き換えられるはずですが、手元の環境では真っ白のままでした。

ハードウェア時刻のお世話をする

まずは$ cat /etc/adjtimeでadjtimeファイルの中身を見てみましょう。

/etc/adjtime
0.000000 1510044982 0.000000
1510044982
UTC

まず、3行目はタイムゾーンではなく「UTCかローカルタイムか」が書かれている部分です。ローカルタイムの場合、LOCALと書かれますが先ほど書いた通りそれは推奨されませんし、timedatectl(8)で変更した場合ここが書き換えられるので、手で触れることはないでしょう。

で、2行目と1行目の真ん中にあるのがdrift値で、ここに整数が入っていれば一回以上このファイルは書き込まれているわけです。
1行目の両端にある数字は、おそらく2回以上drift調整が行われた時に入る差分の値または係数かと思います3

1行目、2行目がオール0だった場合、これまたコマンド一発# hwclock --utc --update-drift --systohcで書くことができます。
しかし、システムクロックとハードウェアクロックの差分で調整するという仕組み上どうしても一回書くだけではあまり意味をなしてくれないでしょう。何らかの事情でNTPが機能しなくなった場合には当然役に立ちますから、週一や月一でsystemd.timer(5)なりcron(8)なりに入れておいて損はないでしょう4

なお、ntpdを運用中の場合はどうもntpd自身がよろしく調整してくれるらしいという情報も(但し手元の環境ではそんなことありませんでした)。その場合は下手に触らない方がいいと思います。

調整の完了

単に$ timedatectl status$ cat /etc/adjtimeの出力を確認して、おかしなところがなければOKです。
hwclockコマンドをtimer作ったりcronに入れたりした人は、drift値の変動が収まったタイミングを見計らって# systemctl disableなりcrontabから削除なりしても良いでしょう。

お疲れ様でした。


  1. ある事情のためPiで使ってるので知っていますが、ハリセンボン族の一員であるopenntpdにはopenntpdとしてのmanpageはありません。その代わり、具体的なコマンドについてのntpd(8)やntpctl(8)がありますが、他を快調にカッコ付けした続きにこうくるとかなり難しいものがあります。。一般的な方のntpdと丸かぶり。 

  2. Archwikiによれば、Windows側をUTCなハードウェアクロックに適応させる方法もあるようです。 

  3. このファイル、ググった限りでは正確な定義がどこにも載っていないのです。hwclock(8)のソースを読めば多分わかるのでしょうがそこまではやっておらず。。 

  4. systemd.timer(5)を使った場合はサービスファイルも書かねばなりませんが、ジャーナルに出力をリダイレクトさせることができるので--debug付きのサービスファイルを書いておけば時刻調整の様子を克明に知ることができるようになります。