切迫した事情があったわけではありませんが、気になって調べたので結果をまとめておきます。
テスト環境はopenSUSE Tumbleweedですが、まぁsystemd環境では大概同じでしょう。
まずはsystemdに尋ねる
$ timedatectl status
して、得られる出力はこんな感じになります。
$ 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
$
ただし上例は一点を除いて全く正常で、その点も例外事項で異常ではありません。
で、以下の箇所を確認しましょう。
- NTPを使う設定になっているのに
NTP synchronized: no
になっていないか - 特別な理由がないのに
RTC in local TZ: yes
になっていないか
NTPが機能するようにする
お使いのディストリビューションでどのNTPデーモンを使っているかに注意して、使用中のNTPデーモンの設定を確認しましょう。
systemd-timesyncd(8)、ntpd(1)、chrony(1)、openntpd1など色々な実装がありますが、Network time on: yes
となるのはsystemd-timesyncdがenabledな場合に限られます2ので多くの環境では当該項目はあてにならないことを頭に入れておいてください。先ほどの例では、ntpd(1)により時刻が同期されていたためnoながらNTP synchronized: yes
になっています。
ここでは各実装における設定ファイルの書き方には触れません。
RTCがローカル時刻に設定されている場合
Windows環境を上書きしてインストールした環境などでよくなっていますが、Linuxにおいてこの状態は好ましくありません3。Windowsとのデュアルブート仕様である4などといった特別な事情がなければ、コマンド一発# timedatectl set-local-rtc 0
で直してしまいましょう。
なお、この操作により/etc/adjtime
5が書き換えられるはずですが、手元の環境では真っ白のままでした。
ハードウェア時刻のお世話をする
まずは$ cat /etc/adjtime
でadjtimeファイルの中身を見てみましょう。
0.000000 1510044982 0.000000
1510044982
UTC
まず、3行目はタイムゾーンではなく「UTCかローカルタイムか」が書かれている部分です。ローカルタイムの場合、LOCALと書かれますが先ほど書いた通りそれは推奨されませんし、timedatectl(8)で変更した場合ここが書き換えられるので、手で触れることはないでしょう。
で、2行目と1行目の真ん中にあるのがdrift値で、ここに整数が入っていれば一回以上このファイルは書き込まれているわけです。
1行目の両端にある数字は、おそらく2回以上drift調整が行われた時に入る差分の値または係数かと思います6。
1行目、2行目がオール0だった場合、これまたコマンド一発# hwclock --utc --update-drift --systohc
で書くことができます。
しかし、システムクロックとハードウェアクロックの差分で調整するという仕組み上どうしても一回書くだけではあまり意味をなしてくれないでしょう。何らかの事情でNTPが機能しなくなった場合には当然役に立ちますから、週一や月一でsystemd.timer(5)なりcron(8)なりに入れておいて損はないでしょう7。
なお、ntpdを運用中の場合はどうもntpd自身がよろしく調整してくれるらしいという情報も(但し手元の環境ではそんなことありませんでした)。その場合は下手に触らない方がいいと思います。
調整の完了
単に$ timedatectl status
と$ cat /etc/adjtime
の出力を確認して、おかしなところがなければOKです。
hwclockコマンドをtimer作ったりcronに入れたりした人は、drift値の変動が収まったタイミングを見計らって# systemctl disable
なりcrontabから削除なりしても良いでしょう。
お疲れ様でした。
-
ある事情のためPiで使ってるので知っていますが、ハリセンボン族の一員であるopenntpdにはopenntpdとしてのmanpageはありません。その代わり、具体的なコマンドについての
ntpd(8)
やntpctl(8)
がありますが、他を快調にカッコ付けした続きにこうくるとかなり難しいものがあります。。一般的な方のntpdと丸かぶり。 ↩ -
20181020追記:
この項目の名前ですが、現在のsystemdでは→20181228追記:バージョン239でsystemd-time-sync-wait.serviceなるものが追加され、同時にsystemd-timesyncd.service active
というものに変更されています。普通のNTPデーモン使ってる人には微妙な変更ですよね。time-sync.target
あたりで上手いことできないのでしょうか。NTP service
というジェネリックな表記に変わった ので今後のディストリビューションではこの辺の微妙さは解消されていることでしょう。 ↩ -
その理由はArchWikiに書かれており、要約すると「これをやると夏時間の類による切り替えをLinux側ではハンドルできず、それだけのためにローカル時刻RTCの実装された別のOSを起動する必要が発生する」というものであるようです。 ↩
-
2015年の更新で現れたFHS3.0において、このパスは
/var/lib/hwclock/adjtime
というものに定義の変更がされています。しかし2018年10月現在util-linux側ではこの変更に追従していないため、現在もほとんどの環境では/etc/adjtime
となっているはずです。 ↩ -
このファイル、ググった限りでは正確な定義がどこにも載っていないのです。hwclock(8)のソースを読めば多分わかるのでしょうがそこまではやっておらず。。→20180904追記:読みました。私の稚拙なCスキルで読んだ限りですが、どうも右端の数字は「RTCを書けないが読めはするプログラムがズレを認識した時にここに書いておくと、hwclock(8)はこれを加味してズレを計測する」といったような役割があるようです。つまりRTCに触れる存在がhwclock(8)のみであればここの値は誰も書かないので0こそ正常値だということのようです。 ↩
-
systemd.timer(5)を使った場合はサービスファイルも書かねばなりませんが、ジャーナルに出力をリダイレクトさせることができるので--verbose付きのサービスファイルを書いておけば時刻調整の様子を克明に知ることができるようになります。 ↩