システム時刻管理とは

Linuxサーバーの多くは、ログの時刻、認証(Kerberosなど)、分散システム間の整合性、スケジュールされたジョブの実行など、さまざまな場面で正確な時刻に依存しています。Linuxが扱う「時刻」には、大きく分けて2種類あります。

画像
  • システムクロック(system clock):カーネルが管理する時刻で、OSが起動している間、実際にアプリケーションやコマンドが参照する時刻です。内部的にはUTCを基準として扱われ、タイムゾーンに応じたローカル時刻への変換は表示時に行われます。
  • ハードウェアクロック(hardware clock、RTC=Real Time Clockとも呼ばれます):マザーボード上の電池でバックアップされた時計で、システムの電源が切れている間も時を刻み続けます。システムクロックは、起動時にこのハードウェアクロックの値を読み込んで初期化されます。

この2つは別々の時計であるため、放っておくと徐々にずれが生じます(クロックドリフト)。そのため、Linuxシステムの時刻管理は、大きく「(1) ハードウェアクロックとシステムクロックを整合させる」「(2) ネットワーク経由でより正確な基準時刻(NTPサーバー)と同期する」という2つの仕組みで成り立っています。本記事では、この両方について、代表的なコマンドと設定ファイルを解説します。

ハードウェアクロックとシステムクロックの同期

hwclock

hwclockは、ハードウェアクロックの値を表示・設定したり、システムクロックとの間で値をコピーしたりするためのコマンドです。ハードウェアクロックの設定やシステムクロックへの反映には管理者権限が必要です。表示には、環境のRTCデバイスのアクセス権限によっては管理者権限を要しない場合があります。主なオプションは次のとおりです。

  • hwclock(引数無し):現在のハードウェアクロックの値を表示します。
  • hwclock --hctosys:ハードウェアクロックの値を読み取り、ドリフト(後述)を補正したうえでシステムクロックに反映します(Hardware Clock to System clock)。多くのディストリビューションでは、起動シーケンスの中でこの処理が自動的に行われます。
  • hwclock --systohc:現在のシステムクロックの値をハードウェアクロックに書き込みます(System clock to Hardware Clock)。あわせて、後述する/etc/adjtimeのタイムスタンプも更新されます。
  • hwclock --set --date '文字列':指定した日時をハードウェアクロックに直接設定します。

ハードウェアクロックのタイムスケール(UTCかローカル時刻か)

ハードウェアクロック自体は「協定世界時(UTC)を保持しているのか、ローカル時刻を保持しているのか」という情報を、時計データそのものの中には持っていません。そのため、この情報は/etc/adjtimeという設定ファイルの3行目(UTCまたはLOCALという文字列)に別途記録されます。hwclockコマンドに--utc/--localtimeオプションを明示しなかった場合は、この/etc/adjtimeの記録を参照し、ファイル自体が存在しない場合はUTCが既定値として扱われます。

なぜUTC運用が推奨されるか

ハードウェアクロックをローカル時刻で運用していると、夏時間(サマータイム)の切り替えのタイミングでLinuxが起動していなかった場合に、切り替え後の補正が正しく反映されないなどの不整合が起こり得ます。ハードウェアクロックをUTCで運用していれば、夏時間の切り替えは表示時のタイムゾーン変換側(ソフトウェア)で一貫して処理されるため、この種の問題を避けられますこの理由から、多くの解説ではハードウェアクロックをUTCで運用することが推奨されていますが、実務上は他OSとのデュアルブート環境(Windowsはハードウェアクロックをローカル時刻として扱うことが多い)などの事情でローカル時刻運用が選ばれる場合もあります。「UTCでなければならない」という断定はできない点に注意してください。[1]。

システムクロックを確認・設定するコマンド

date

dateは、システムクロックの現在時刻を表示(または、権限があれば設定)するコマンドです。

  • date(引数無し):現在のシステムクロックの日時を、システムのタイムゾーン設定に従って表示します。
  • date -u(--utc):時刻をUTCで表示します。
  • date -s '文字列'(--set):システムクロックを指定した値に設定します(管理者権限が必要です)。
  • date +書式:%Y(西暦4桁)・%m(月)・%d(日)・%H(時)・%M(分)・%S(秒)・%s(1970年1月1日00:00:00 UTCからの経過秒数)などの書式指定子で、任意の形式で時刻を表示できます。

date -sでシステムクロックを直接変更しても、ハードウェアクロック側は自動的には更新されません。変更を恒久的に反映させたい場合は、別途hwclock --systohcを実行する必要があります。

timedatectl

timedatectlは、systemdが提供する、時刻・タイムゾーン・NTPによる自動同期の設定をまとめて扱うコマンドです。systemdを採用していないシステムでは利用できません。

※timedatectlコマンドの使用例は「ロケールとタイムゾーン」の記事で紹介しています。

タイムゾーンに関する前提知識

NTPによる時刻同期の話に入る前に、時刻の「表示のされ方」を決めるタイムゾーンの仕組みを簡単に確認しておきますタイムゾーンとロケールについてのより詳しい解説は、別記事「ロケールとタイムゾーンの設定」も参照してください。[2]。

/usr/share/zoneinfo/

世界各地のタイムゾーン定義(UTCからの時差、サマータイムの規則など)を収録したデータベースファイル群が置かれているディレクトリです。Asia/Tokyoのように「地域/都市名」に対応するファイル構成になっています。

/etc/localtime

システムで現在使われているタイムゾーンを指し示すファイルです。通常は/usr/share/zoneinfo/配下の該当ファイルへのシンボリックリンクとして構成されますが、リンクではなくファイルのコピーが置かれる場合もあります。timedatectl set-timezoneを実行すると、このファイルが自動的に更新されます。

/etc/timezone

現在のタイムゾーン名(例:Asia/Tokyo)をプレーンテキストで保存したファイルで、主にDebian/Ubuntu系のディストリビューションで使われています。すべてのディストリビューションに存在するファイルではなく、タイムゾーンの決定そのものに使われるのは/etc/localtimeの方である点に注意してください。

NTPによる時刻同期の考え方

画像

システムクロックとハードウェアクロックの整合が取れていても、ハードウェアクロック自体の精度には限界があり、時間の経過とともに実際の時刻とのずれ(ドリフト)が蓄積していきます。この問題に対応するため、ネットワーク経由でより正確な基準時刻を持つサーバーと定期的に同期する仕組みがNTP(Network Time Protocol)です。

Linuxでよく使われるNTPクライアント・デーモンの実装には、主に次の2種類があります。

  • ntpd:NTPプロトコルの伝統的な参照実装(ntpプロジェクト由来)のデーモンです。
  • chronyd:比較的新しい実装で、間欠的にしかネットワークに接続できない環境(ノートPCなど)や、仮想マシンのように起動直後にクロックが大きくずれやすい環境への対応に重点を置いて設計されています。

近年は多くのディストリビューションでchronyが標準採用される傾向にありますが、これはディストリビューションやバージョンによって異なり、「Linuxでは必ずchronyが使われる」とは言い切れません。両方とも試験範囲に含まれるため、双方の基本的な設定ファイル・コマンドを押さえておく必要があります。

systemd-timesyncdとの違い(補足)

systemdには、ntpdやchronydとは別に、systemd-timesyncdという軽量なSNTP(Simple NTP)クライアントが同梱されています。timedatectl set-ntp trueを実行したときに、そのシステムでデフォルトで有効化される同期サービスとして動作している場合があります。時刻を受信するだけの簡易なクライアント機能に限定されており、他のホストに時刻を配信するサーバー機能は持ちません。ntpdやchronydをインストール・有効化した場合は、二重に時刻同期が行われないよう、通常はどちらか一方のみを動作させます。

ntpdによる時刻同期

/etc/ntp.conf

ntpdの設定ファイルです。同期先のNTPサーバーをserver行またはpool行で指定します。

driftfile /var/lib/ntp/ntp.drift
restrict default kod nomodify notrap nopeer noquery
restrict 127.0.0.1
restrict ::1
pool pool.ntp.org iburst
  • driftfile:計算したクロックドリフト(時計の進み・遅れの傾向)を保存しておくファイルの場所を指定します。再起動後もこの値を引き継ぐことで、より早く安定した同期状態に到達できます。このファイルのパスはディストリビューションやパッケージ設定により異なります。
  • restrict:どのホストからのアクセスをどこまで許可するかを制御するアクセス制御行です。
  • server:単一の同期先NTPサーバーを指定します。
  • pool:複数のNTPサーバーで構成されるプールを同期先として指定します。末尾のiburstは、起動直後に短い間隔で複数のパケットを送ることで、通常より早く同期を確立するためのオプションです。

なお、ntpパッケージ(ntpd・/etc/ntp.conf一式)自体が既定ではインストールされておらず、chronyが標準になっているディストリビューションも増えているため、「どのLinuxにも/etc/ntp.confが存在する」とは限らない点に注意してください。

ntpd

ntpdは、/etc/ntp.confの設定に従って常駐し、継続的にNTPサーバーとの時刻同期を行うデーモンです。一般に、常駐起動して時刻を合わせ続けることを想定しているため、既定の動作では、同期先との時刻差が一定以上(1000秒程度)大きい場合には安全のため自動補正を行わず、管理者による対応を促します。

ntpdate

ntpdateは、指定したNTPサーバーに1回だけ問い合わせて、その場でシステムクロックを補正する(ntpdのように常駐しない)コマンドです。かつては、ntpdを起動する前に大まかな時刻合わせをしておく目的などでよく使われていました。

現在は非推奨(deprecated)とされている点に注意してください。NTPプロジェクト自身のドキュメントでは、ntpdとsntpの組み合わせによってntpdateが担っていた機能がカバーされるようになったとして、ntpdateは将来的に廃止(retire)される方針が示されています起動時の1回限りの補正が必要な場合の代替としては、設定ファイルの同期先を用いて時刻を合わせて終了するntpd -gqやsntpコマンドが案内されています。iburstを利用する場合は、設定ファイルのserver行またはpool行に指定します。ディストリビューションによっては、ntpdateパッケージの提供自体を終了している場合もあります。[3]。試験対策としては、「ntpdateは現在では非推奨の一度きり実行のコマンドである」という位置づけを押さえておけば十分です。

chronyによる時刻同期

/etc/chrony.conf(ディストリビューションにより異なる)

chronydの設定ファイルです。RHEL系では/etc/chrony.confが、Debian/Ubuntu系では/etc/chrony/chrony.confが代表的な設定ファイルのパスです。

pool pool.ntp.org iburst
driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
  • pool:DNSの名前解決で複数のIPアドレスに展開されるサーバー群(プール)を同期先として指定します。pool.ntp.orgのような、複数のサーバーで構成されるプールを指定する場合に使います(単一のサーバーを指定する場合はserver行を使います)。
  • driftfile:ntpdと同様、クロックドリフトの記録先です。
  • makestep:システムクロックと同期先との差が大きい場合に、時刻を徐々に合わせる(slew)のではなく、一気に飛ばして合わせる(step)ことを許可する条件を指定します。makestep 1.0 3では、時刻差が1.0秒を超える場合にステップ補正を許可し、この判定を最初の3回のクロック更新に限ります。chronydは起動直後の大きなずれにも対応しやすいよう設計されており、この設定はその挙動の一部です。
  • rtcsync:システムクロックが同期した際に、ハードウェアクロックへも定期的に反映させる設定です。

chronyc

chronycは、稼働中のchronydに接続して状態を確認したり、設定を操作したりするためのコマンドラインクライアントです(chronydが起動していない場合は正しく動作しません)。主なサブコマンドは次のとおりです。

  • chronyc tracking:現在の同期状態(基準としているサーバー、システムクロックとのオフセット、推定される周波数ドリフトなど)を表示します。
  • chronyc sources:設定されている同期先候補の一覧と、それぞれの選択状態(現在選ばれている基準か、候補か、到達不能かなど)を表示します。
  • chronyc sourcestats:各同期先について、これまでの測定値の統計情報(推定される周波数オフセットやばらつきなど)を表示します。
  • chronyc makestep:設定ファイルの条件を待たず、その場で強制的にステップ補正を行います。

pool.ntp.org

pool.ntp.orgは、NTP Poolプロジェクトが運営する、ボランティアによって提供された多数のNTPサーバー群(プール)です。単一の固定サーバーではなく、DNSの仕組みによって複数のサーバーのアドレスが動的に返され、問い合わせ時の状況やDNSキャッシュによって返されるアドレスが変わることがあります。特定の1台に負荷が集中しないよう設計されています。asia.pool.ntp.orgやjp.pool.ntp.orgのように、大陸・国単位のサブドメインも用意されており、地理的に近いサーバー群を優先的に使うこともできます。前述の/etc/ntp.conf・/etc/chrony.confの設定例のように、pool行の同期先として指定するのが一般的な使い方です。


補足

  1. この理由から、多くの解説ではハードウェアクロックをUTCで運用することが推奨されていますが、実務上は他OSとのデュアルブート環境(Windowsはハードウェアクロックをローカル時刻として扱うことが多い)などの事情でローカル時刻運用が選ばれる場合もあります。「UTCでなければならない」という断定はできない点に注意してください。 ↩
  2. タイムゾーンとロケールについてのより詳しい解説は、別記事「ロケールとタイムゾーンの設定」も参照してください。 ↩
  3. 起動時の1回限りの補正が必要な場合の代替としては、設定ファイルの同期先を用いて時刻を合わせて終了するntpd -gqやsntpコマンドが案内されています。iburstを利用する場合は、設定ファイルのserver行またはpool行に指定します。ディストリビューションによっては、ntpdateパッケージの提供自体を終了している場合もあります。 ↩