「システム時刻」の版間の差分

提供: ArchWiki
ナビゲーションに移動 検索に移動
(同期)
(小改動)
 
(4人の利用者による、間の43版が非表示)
1行目: 1行目:
 
[[Category:メインボードと BIOS]]
 
[[Category:メインボードと BIOS]]
 
[[Category:システム管理]]
 
[[Category:システム管理]]
[[en:Time]]
+
[[en:System time]]
[[es:Time]]
+
[[es:System time]]
 
[[fa:زمان]]
 
[[fa:زمان]]
[[fr:Horloge]]
+
[[fr:System time]]
[[ru:Time]]
+
[[zh-hans:System time]]
[[zh-hans:Time]]
+
[[zh-hant:System time]]
 
{{Related articles start}}
 
{{Related articles start}}
  +
{{Related|ネットワークタイムプロトコルデーモン}}
{{Related|Network Time Protocol daemon}}
 
 
{{Related|OpenNTPD}}
 
{{Related|OpenNTPD}}
 
{{Related|Chrony}}
 
{{Related|Chrony}}
14行目: 14行目:
 
{{Related articles end}}
 
{{Related articles end}}
   
オペレーティングシステムでは、時間(時計)4つの値から成ります: 時・時刻系・標準時間帯・夏時間 (Daylight Saving Time, DST)。この記事ではれらが何なのか、そしてどうやって読み込み・設定するのか説明します。ネットワークを使って正確なシステム時刻を''維持する''方法は [[Network Time Protocol]] を見て下さい。
+
オペレーティング システムでは、時間 (クロック) 3 つの部分によって決定されます: 時間の、現地時間か UTC かそれ以外か、タイム ゾーン、および該当する場合は夏時間 (DST) です。この記事では、それらが何であるか、およびれらの読み取り/設定方法について説明します。システムには、ハドウェア ロックとシステム クロックの 2 つのクロックが存在します。これにつても、この記事で詳しく説明します
   
  +
ほとんどのオペレーティング システムの標準的な動作は次のとおりです。
== ハードウェアクロックとシステムクロック ==
 
   
コンピューターは2つの計を持っていることを考慮しなくてはなりません: "ハードウェアクロック" と "システム(ソフトウェア)クロック" です。
+
* 起動ハードウェア クロックからシステム クロックを設定します。
  +
* システムクロックの正確な時刻を維持します。[[#時刻同期]] を参照してください。
  +
* シャットダウン時にシステム クロックからハードウェア クロックを設定します。
   
  +
== ハードウェアクロック ==
'''ハードウェアクロック''' (又の名をリアルタイムクロック (Real Time Clock, RTC) もしくは CMOS クロック) は次の値を保存しています: 年・月・日・時・分・秒。時刻系 (localtime か UTC) や夏時間が使われているかどうかの情報を保存することはできません。
 
  +
  +
'''ハードウェアクロック''' (又の名をリアルタイムクロック (Real Time Clock, RTC) もしくは CMOS クロック) は次の値を保存しています: 年・月・日・時・分・秒。2016 年以降の[[UEFI]] ファームウェアには、タイムゾーンとサマータイムを保存する機能を備えられています。
  +
  +
=== ハードウェアクロックの読み込み ===
  +
  +
# hwclock --show
  +
  +
=== システムクロックからハードウェアクロックを設定する ===
  +
  +
以下は、システムクロックからハードウェアクロックを設定するものです。さらに、{{ic|/etc/adjtime}} を更新するか、存在しない場合は作成します。このファイルに関するより詳しい情報は [[#タイムスキュー]] の項と同様に {{man|8|hwclock|The Adjtime File}} を参照してください。
  +
  +
# hwclock --systohc
  +
  +
== システムクロック ==
   
 
'''システムクロック''' (又の名をソフトウェアクロック) は次の情報を記録しています: 時刻、タイムゾーン、そして DST が適用されるかどうか。Linux カーネルは1970年1月1日の午前0時からの秒数でシステムクロックをはじき出します。システムクロックの初期値は {{ic|/etc/adjtime}} を使ってハードウェアクロックから算定されます。起動が完了した後は、システムクロックはハードウェアクロックとは独立して動作します。Linux カーネルはタイマー割り込みを数えることによりシステムクロックを記録します。
 
'''システムクロック''' (又の名をソフトウェアクロック) は次の情報を記録しています: 時刻、タイムゾーン、そして DST が適用されるかどうか。Linux カーネルは1970年1月1日の午前0時からの秒数でシステムクロックをはじき出します。システムクロックの初期値は {{ic|/etc/adjtime}} を使ってハードウェアクロックから算定されます。起動が完了した後は、システムクロックはハードウェアクロックとは独立して動作します。Linux カーネルはタイマー割り込みを数えることによりシステムクロックを記録します。
26行目: 42行目:
 
=== 時刻を表示する ===
 
=== 時刻を表示する ===
   
現在のシステム時刻を確認するには (UTC と地時どちらも表示されます):
+
現在のシステム時刻を確認するには (UTC と地時間のどちらも表示されます):
   
 
$ timedatectl status
 
$ timedatectl status
50行目: 66行目:
 
== 時刻系 ==
 
== 時刻系 ==
   
  +
2つの時刻系が存在します: 地方時 ('''localtime''') と [[Wikipedia:ja:協定世界時|協定世界時]] ('''C'''oordinated '''U'''niversal '''T'''ime, '''UTC''') です。地方時系は現在の''タイムゾーン''によって決まりますが、UTC は''世界時''であり、タイムゾーンの値は関係ありません。概念的には異なっていますが、UTC は GMT (グリニッジ標準時, Greenwich Mean Time) とも言われます。
{{Note|{{ic|/etc/adjtime}} が存在しない場合、デフォルトで [[systemd]] はハードウェアクロックに UTC を使用します。}}
 
 
2つの時刻系が存在します: 地方時 ('''localtime''') と 協定世界時 ('''C'''oordinated '''U'''niversal '''T'''ime, '''UTC''') です。地方時系は現在の''タイムゾーン''によって決まりますが、UTC は''世界時''であり、タイムゾーンの値は関係ありません。概念的には異なっていますが、UTC は GMT (グリニッジ標準時, Greenwich Mean Time) とも言われます。
 
   
 
ハードウェアクロック (CMOS クロック, BIOS で表示される時間) で使われる時刻系はオペレーティングシステムによって定義されます。デフォルトでは、Windows は localtime を使いますが、Mac OS は UTC を使っていて、UNIX ライクなオペレーティングシステムでは決まっていません。一般的に、UTC を使う OS は起動時に CMOS (ハードウェアクロック) の時間を UTC 時間 (GMT, Greenwich time) だと認識して、あなたのタイムゾーンによってその時間を調整してシステム時刻を設定します。
 
ハードウェアクロック (CMOS クロック, BIOS で表示される時間) で使われる時刻系はオペレーティングシステムによって定義されます。デフォルトでは、Windows は localtime を使いますが、Mac OS は UTC を使っていて、UNIX ライクなオペレーティングシステムでは決まっていません。一般的に、UTC を使う OS は起動時に CMOS (ハードウェアクロック) の時間を UTC 時間 (GMT, Greenwich time) だと認識して、あなたのタイムゾーンによってその時間を調整してシステム時刻を設定します。
   
Linux を使う時はハードウェアクロックを UTC 時刻系に設定するのが有益です。Linux でハードウェアクロックを UTC で定義すれば夏時間が自動的使わます。地方時系を使う場合、システム刻は DST によってわらなくなり他のオペレーティングシステムが DST の切り替え引き受けことになります (そ NTP は動作しせん)
+
複数のオペレーティングシステムがマシンにインストールされている場合、それらすべて同じハードウェアクロックから現在の時刻取得します。システム間の競合を避けるために、UTC に設定することをお勧めします。それ以外の場合、ハードウェアクロックが「現地時間設定さている場合、たとえば [[Wikipedia:ja:夏間|DST]] 更後に複数のオペレーティングシステムがそれ調整す可能性があ、その結果、過剰な修正が行われます。異なるタイムゾーン間を移動、オペレーティング システムの 1 つを使用してシステム/ハドウア クロックをリセッするときにも、問題が発生する可能性があり
   
ハードウェアクロックの時刻系の設定はコマンドラインから可能す。Arch Linux をインストールした時にあなたがどちらを設定したのか確認るには:
+
ハードウェアクロックは、{{ic|timedatectl}} コマンドで照会および設定ができま
  +
以下を使用して、Arch システムの現在のハードウェアクロック時間標準を確認できます。
  +
  +
{{hc|$ timedatectl {{!}} grep local|
  +
RTC in local TZ: no
  +
}}
   
$ timedatectl status | grep local
 
   
 
ハードウェアクロックは {{ic|timedatectl}} コマンドで尋ねたり設定できます。ハードウェアクロックの時刻系を localtime に変更するには次を実行してください:
 
ハードウェアクロックは {{ic|timedatectl}} コマンドで尋ねたり設定できます。ハードウェアクロックの時刻系を localtime に変更するには次を実行してください:
66行目: 84行目:
 
# timedatectl set-local-rtc true
 
# timedatectl set-local-rtc true
   
逆に時刻系を UTC設定するには次を実行してください:
+
ハードウェアクロックの時刻系を localtime変更するには次を実行してください:
   
# timedatectl set-local-rtc false
+
# timedatectl set-local-rtc '''1'''
   
  +
逆にハードウェアクロックの時刻系を UTC に戻すには次を実行してください:
ハードウェアクロック (RTC) を localtime に設定すると、夏時間の扱いで問題が生じるので注意してください。コンピュータの電源が切られている時に夏時間が変わると、次の起動時に時計がおかしくなります (詳しくは [http://www.cl.cam.ac.uk/~mgk25/mswish/ut-rtc.html ここ] を見て下さい)。最近のカーネルでは起動時にシステム時刻を直接 RTC からセットしますが、その際カーネルは RTC を UTC としてみなします。RTC が localtime だった場合、起動時に毎回システム時刻は間違って設定され、その後修正されることになります。これは予期せぬバグを引き起こす温床になりかねません (時計の針が戻るのは良いことばかりではないのです)。
 
   
  +
# timedatectl set-local-rtc '''0'''
上のコマンドで {{ic|/etc/adjtime}} が自動的に設定されます; 他の設定は必要ありません。
 
  +
  +
これらは {{ic|/etc/adjtime}} を自動的に生成し、それに応じて RTC を更新します。これ以上の設定は必要ありません。
   
 
カーネルの起動中、RTC ドライバーがロードされた時点で、ハードウェアクロックからシステムクロックを設定することができます。設定するかどうかはハードウェアプラットフォーム、カーネルのバージョン・ビルドオプション次第です。設定される場合、ブートシーケンスで既に、ハードウェアクロックは UTC と認識され {{ic|/sys/class/rtc/rtcN/hctosys}} (N=0,1,2,..) の値は 1 に設定されます。その後、{{ic|/etc/adjtime}} の値を使って、再度 systemd によってハードウェアクロックからシステムクロックが設定されます。そのため、ハードウェアクロックで localtime を使っているとブートシーケンス中に予期しない動作が発生するかもしれません。例えば、システム時刻が後戻りするなど。従ってこの設定は良いアイデアとは言えません。
 
カーネルの起動中、RTC ドライバーがロードされた時点で、ハードウェアクロックからシステムクロックを設定することができます。設定するかどうかはハードウェアプラットフォーム、カーネルのバージョン・ビルドオプション次第です。設定される場合、ブートシーケンスで既に、ハードウェアクロックは UTC と認識され {{ic|/sys/class/rtc/rtcN/hctosys}} (N=0,1,2,..) の値は 1 に設定されます。その後、{{ic|/etc/adjtime}} の値を使って、再度 systemd によってハードウェアクロックからシステムクロックが設定されます。そのため、ハードウェアクロックで localtime を使っているとブートシーケンス中に予期しない動作が発生するかもしれません。例えば、システム時刻が後戻りするなど。従ってこの設定は良いアイデアとは言えません。
  +
  +
その後、{{ic|/etc/adjtime}} の値に応じて、systemd によってハードウェアクロックからシステムクロックが再度設定されます。したがって、ハードウェアクロックで localtime を使用すると、ブートシーケンス中に予期しない動作が発生する可能性があります。たとえば、システム時間が逆行することは、常に悪い考えです ([https://www.cl.cam.ac.uk/~mgk25/mswish/ut-rtc.html 他にもたくさんあります])。ハードウェアクロックが UTC に設定されていてローカルタイムゾーンについてカーネルに通知しないでください。その結果、Linux システムが使用する FAT ファイルシステムのタイムスタンプは UTC になります。
  +
 
{{Note|
 
{{Note|
* {{ic|timedatectl}} を使うには dbus が有効になっている必要があります。そのため、(インストール中など) chroot 下でこのコマンドが使えないかもしれません。そのような場合には、hwclock コマンドを使って下さい。
+
* {{ic|timedatectl}} を使うには [[D-Bus]] が有効になっている必要があります。そのため、(インストール中など) chroot 下でこのコマンドが使えないかもしれません。そのような場合には、hwclock コマンドを使って下さい。
 
* {{ic|/etc/adjtime}} が存在しない場合、[[systemd]] はハードウェアクロックが UTC に設定されていると認識しています。}}
 
* {{ic|/etc/adjtime}} が存在しない場合、[[systemd]] はハードウェアクロックが UTC に設定されていると認識しています。}}
   
151行目: 174行目:
   
 
また、{{aur|tzupdate}} ツールは IP アドレスの位置情報を元にタイムゾーンを自動設定します。
 
また、{{aur|tzupdate}} ツールは IP アドレスの位置情報を元にタイムゾーンを自動設定します。
  +
  +
==== NetworkManager がネットワークに接続するたびにタイムゾーンを更新する ====
  +
  +
[[NetworkManager# NetworkManager dispatcher を使用したネットワークサービス|NetworkManager dispatcher スクリプト]] を作成します:
  +
  +
{{hc|/etc/NetworkManager/dispatcher.d/09-timezone|
  +
#!/bin/sh
  +
case "$2" in
  +
up)
  +
timedatectl set-timezone "$(curl --fail <nowiki>https://ipapi.co/timezone</nowiki>)"
  +
;;
  +
esac
  +
}}
  +
  +
{{Tip|{{ic|up}} の代わりに {{ic|connectivity-change}} を使用すると、[[OpenConnect]] などのクライアントで VPN に接続するときにタイムゾーンの変更を防ぐことができます。}}
  +
  +
あるいは、ツール {{aur|tzupdate}} が IP アドレスのジオロケーションに基づいてタイムゾーンを自動的に設定します。この [https://medium.com/@ipdata_co/what-is-the-best-commercial-ip-geolocation-api-d8195cda7027 最も人気のある IP 地理位置情報 API の比較] は、プロダクションでどの API を使うか決める際に役に立つかもしれません。
   
 
== クロックスキュー ==
 
== クロックスキュー ==
170行目: 210行目:
 
[[Wikipedia:ja:Network Time Protocol|Network Time Protocol]] (NTP) はパケット交換でデータの遅延時間が不確定なネットワークを介してコンピュータシステムの時刻を同期するためのプロトコルです。NTP の実装は以下が存在します:
 
[[Wikipedia:ja:Network Time Protocol|Network Time Protocol]] (NTP) はパケット交換でデータの遅延時間が不確定なネットワークを介してコンピュータシステムの時刻を同期するためのプロトコルです。NTP の実装は以下が存在します:
   
  +
* {{App|[[Chrony]]|ローミングフレンドリーで、常時オンラインではないシステムのために特別に設計されたクライアントとサーバーです。ほとんどの場合、ntpd よりも速く、より参照に近い形で収束します。|https://chrony.tuxfamily.org/|{{Pkg|chrony}}}}
 
* {{App|[[Network Time Protocol daemon]]|プロトコルの[[Wikipedia:ja:リファレンス実装|リファレンス実装]]であり、特に時刻サーバーでの使用が推奨されます。NTPd は割り込みの周期や1秒辺りのティックの数を調整してシステムクロックのずれを減らすことも可能です。NTPd の実行中は11分ごとにハードウェアクロックの再同期も行われます。|http://www.ntp.org/|{{Pkg|ntp}}}}
 
* {{App|[[Network Time Protocol daemon]]|プロトコルの[[Wikipedia:ja:リファレンス実装|リファレンス実装]]であり、特に時刻サーバーでの使用が推奨されます。NTPd は割り込みの周期や1秒辺りのティックの数を調整してシステムクロックのずれを減らすことも可能です。NTPd の実行中は11分ごとにハードウェアクロックの再同期も行われます。|http://www.ntp.org/|{{Pkg|ntp}}}}
  +
* {{App|[[NTPsec]]|NTPd のフォークで、セキュリティに重点を置いています。多くの古いコードが捨てられる以外は、同じように動作します。|https://ntpsec.org/|{{AUR|ntpsec}}}}
  +
  +
適切な NTP ノード以下の機能を持つものは、SNTP("Sinplified" の意)とみなされます。基本的な SNTP クライアントは、長期的なドリフトを追跡することなく、単に 1 つのサーバーから時刻を取得し、すぐに設定することができます。SNTP は精度が低いですが、より少ないリソースで動作します。この精度は通常、デスクトップユーザーや組み込みワークロードには十分ですが、NTP サーバーには受け入れられません。以下は、SNTP を実装しています:
  +
  +
* {{App|[[ConnMan]]|A lightweight network manager with SNTP support.|[https://web.archive.org/web/20210224075615/https://01.org/connman https://01.org/connman (waybackmachine)]|{{Pkg|connman}}}}
  +
* {{App|ntpclient|シンプルなコマンドライン NTP クライアント。|http://doolittle.icarus.com/ntpclient/|{{Aur|ntpclient}}}}
  +
* {{App|[[OpenNTPD]]|クライアントとサーバーの両方を実装する OpenBSD プロジェクト。|http://www.openntpd.org/|{{Pkg|openntpd}}}}
 
* {{App|sntp|NTPd に付属している [[wikipedia:ja:Simple Network Time Protocol|SNTP]] クライアント。''ntpdate'' を置き換えることができ、サーバー以外の環境での使用が推奨されます。|http://www.ntp.org/|{{Pkg|ntp}}}}
 
* {{App|sntp|NTPd に付属している [[wikipedia:ja:Simple Network Time Protocol|SNTP]] クライアント。''ntpdate'' を置き換えることができ、サーバー以外の環境での使用が推奨されます。|http://www.ntp.org/|{{Pkg|ntp}}}}
 
* {{App|[[systemd-timesyncd]]|クライアント側だけを実装したシンプルな [[wikipedia:ja:Simple Network Time Protocol|SNTP]] デーモン。リモートサーバーに時刻を問い合わせることだけを行います。大抵の環境ではクライアントだけで十分です。|https://www.freedesktop.org/wiki/Software/systemd/|{{Pkg|systemd}}}}
 
* {{App|[[systemd-timesyncd]]|クライアント側だけを実装したシンプルな [[wikipedia:ja:Simple Network Time Protocol|SNTP]] デーモン。リモートサーバーに時刻を問い合わせることだけを行います。大抵の環境ではクライアントだけで十分です。|https://www.freedesktop.org/wiki/Software/systemd/|{{Pkg|systemd}}}}
* {{App|[[OpenNTPD]]|クライアントとサーバーの両方を実装する OpenBSD プロジェクト。|http://www.openntpd.org/|{{Pkg|openntpd}}}}
 
* {{App|[[Chrony]]|ノートパソコンなど常にオンラインとは限らない環境用に設計されたクライアント・サーバー。|https://chrony.tuxfamily.org/|{{Pkg|chrony}}}}
 
* {{App|ntpclient|シンプルなコマンドライン NTP クライアント。|http://doolittle.icarus.com/ntpclient/|{{Aur|ntpclient}}}}
 
   
  +
== ユーザー別あるいは一時的に時刻を設定 ==
== ヒントとテクニック ==
 
 
=== fake-hwclock ===
 
 
[https://github.com/xanmanning/alarm-fake-hwclock alarm-fake-hwclock] は RTC をバックアップするバッテリーが搭載されていないシステム用のスクリプトで、シャットダウン時に現在時刻を保存して、起動時に保存した時刻を復元する systemd サービスが付属しています。これによって時刻が飛んでしまうエラーを防ぐことができます。
 
 
{{AUR|fake-hwclock-git}} を[[インストール]]して {{ic|fake-hwclock.service}} を[[Systemd#ユニットを使う|起動・有効化]]してください。
 
 
=== ユーザー別あるいは一時的に時刻を設定 ===
 
   
 
ときとしてシステムの時刻は変えずに一時的に設定を変えたいということがあるでしょう。例えば、時間を使用するアプリケーションを開発していて実際に動きをテストしたい場合やタイムゾーンが異なる場所からサーバーにログインしている場合などです。
 
ときとしてシステムの時刻は変えずに一時的に設定を変えたいということがあるでしょう。例えば、時間を使用するアプリケーションを開発していて実際に動きをテストしたい場合やタイムゾーンが異なる場所からサーバーにログインしている場合などです。
   
アプリケーションにシステム時刻以外の時刻を使わせたいときは ({{Pkg|libfaketime}} に含まれている) ''faketime'' あるいは {{Pkg|datefudge}} ユーティリティが使えます。
+
アプリケーションにシステム時刻以外の時刻を使わせたいときは ({{Pkg|libfaketime}} に含まれている) {{man|1|faketime}} ユーティリティが使えます。
   
 
アプリケーションにシステム設定のタイムゾーン以外のタイムゾーンを使わせたいときは、以下のように {{ic|TZ}} [[環境変数]]を設定してください:
 
アプリケーションにシステム設定のタイムゾーン以外のタイムゾーンを使わせたいときは、以下のように {{ic|TZ}} [[環境変数]]を設定してください:
201行目: 238行目:
   
 
タイムゾーンを別々に設定するケースとして同一システム上にユーザーが複数存在する場合も考えられます。シェルの設定ファイルで {{ic|TZ}} 変数を設定することでユーザーごとにタイムゾーンを設定できます。[[環境変数#変数の定義]]や[[自動起動#シェル]]を参照してください。
 
タイムゾーンを別々に設定するケースとして同一システム上にユーザーが複数存在する場合も考えられます。シェルの設定ファイルで {{ic|TZ}} 変数を設定することでユーザーごとにタイムゾーンを設定できます。[[環境変数#変数の定義]]や[[自動起動#シェル]]を参照してください。
  +
  +
== ヒントとテクニック ==
  +
  +
=== fake-hwclock ===
  +
  +
[https://github.com/xanmanning/alarm-fake-hwclock alarm-fake-hwclock] は RTC をバックアップするバッテリーが搭載されていないシステム用のスクリプトで、シャットダウン時に現在時刻を保存して、起動時に保存した時刻を復元する systemd サービスが付属しています。これによって時刻が飛んでしまうエラーを防ぐことができます。
  +
  +
{{AUR|fake-hwclock-git}} を[[インストール]]して {{ic|fake-hwclock.service}} を[[Systemd#ユニットを使う|起動・有効化]]してください。
   
 
== トラブルシューティング ==
 
== トラブルシューティング ==
221行目: 266行目:
 
* {{Pkg|tzdata}} で使われている [http://www.twinsun.com/tz/tz-link.htm タイムゾーンと夏時間のソース]
 
* {{Pkg|tzdata}} で使われている [http://www.twinsun.com/tz/tz-link.htm タイムゾーンと夏時間のソース]
 
* [https://www.ucolick.org/~sla/leapsecs/timescales.html Time Scales]
 
* [https://www.ucolick.org/~sla/leapsecs/timescales.html Time Scales]
  +
* [[Gentoo: System time]]
 
* [[Wikipedia:ja:時間]]
 
* [[Wikipedia:ja:時間]]
  +
* [https://www.datetimeonline.com/time/gmt-utc-time The Difference Between GMT and UTC]

2024年9月1日 (日) 19:08時点における最新版

関連記事

オペレーティング システムでは、時間 (クロック) は 3 つの部分によって決定されます: 時間の値、現地時間か UTC かそれ以外か、タイム ゾーン、および該当する場合は夏時間 (DST) です。この記事では、それらが何であるか、およびそれらの読み取り/設定方法について説明します。システムには、ハードウェア クロックとシステム クロックの 2 つのクロックが存在します。これについても、この記事で詳しく説明します。

ほとんどのオペレーティング システムの標準的な動作は次のとおりです。

  • 起動時にハードウェア クロックからシステム クロックを設定します。
  • システムクロックの正確な時刻を維持します。#時刻同期 を参照してください。
  • シャットダウン時にシステム クロックからハードウェア クロックを設定します。

ハードウェアクロック

ハードウェアクロック (又の名をリアルタイムクロック (Real Time Clock, RTC) もしくは CMOS クロック) は次の値を保存しています: 年・月・日・時・分・秒。2016 年以降のUEFI ファームウェアには、タイムゾーンとサマータイムを保存する機能を備えられています。

ハードウェアクロックの読み込み

# hwclock --show

システムクロックからハードウェアクロックを設定する

以下は、システムクロックからハードウェアクロックを設定するものです。さらに、/etc/adjtime を更新するか、存在しない場合は作成します。このファイルに関するより詳しい情報は #タイムスキュー の項と同様に hwclock(8) § The Adjtime File を参照してください。

# hwclock --systohc

システムクロック

システムクロック (又の名をソフトウェアクロック) は次の情報を記録しています: 時刻、タイムゾーン、そして DST が適用されるかどうか。Linux カーネルは1970年1月1日の午前0時からの秒数でシステムクロックをはじき出します。システムクロックの初期値は /etc/adjtime を使ってハードウェアクロックから算定されます。起動が完了した後は、システムクロックはハードウェアクロックとは独立して動作します。Linux カーネルはタイマー割り込みを数えることによりシステムクロックを記録します。

時刻を表示する

現在のシステム時刻を確認するには (UTC と現地時間のどちらも表示されます):

$ timedatectl status

root で同じコマンドを実行すればハードウェアクロックの時間も表示します。

時刻を設定する

直接システムクロックを設定するには:

# timedatectl set-time "yyyy-MM-dd hh:mm:ss"

例:

# timedatectl set-time "2014-05-26 11:13:54"

2014年5月26日、11時13分54秒に設定されます。

RTC

ほとんどのオペレーティングシステムは:

  • 起動時にハードウェアクロックからシステムクロックを設定します
  • NTP デーモンを使ってシステムクロックの時間を正確に保ちます
  • シャットダウン時にシステムクロックからハードウェアクロックを設定します

時刻系

2つの時刻系が存在します: 地方時 (localtime) と 協定世界時 (Coordinated Universal Time, UTC) です。地方時系は現在のタイムゾーンによって決まりますが、UTC は世界時であり、タイムゾーンの値は関係ありません。概念的には異なっていますが、UTC は GMT (グリニッジ標準時, Greenwich Mean Time) とも言われます。

ハードウェアクロック (CMOS クロック, BIOS で表示される時間) で使われる時刻系はオペレーティングシステムによって定義されます。デフォルトでは、Windows は localtime を使いますが、Mac OS は UTC を使っていて、UNIX ライクなオペレーティングシステムでは決まっていません。一般的に、UTC を使う OS は起動時に CMOS (ハードウェアクロック) の時間を UTC 時間 (GMT, Greenwich time) だと認識して、あなたのタイムゾーンによってその時間を調整してシステム時刻を設定します。

複数のオペレーティングシステムがマシンにインストールされている場合、それらはすべて同じハードウェアクロックから現在の時刻を取得します。システム間の競合を避けるために、UTC に設定することをお勧めします。それ以外の場合、ハードウェアクロックが「現地時間」に設定されている場合、たとえば DST の変更後に複数のオペレーティングシステムがそれを調整する可能性があり、その結果、過剰な修正が行われます。異なるタイムゾーン間を移動し、オペレーティング システムの 1 つを使用してシステム/ハードウェア クロックをリセットするときにも、問題が発生する可能性があります。

ハードウェアクロックは、timedatectl コマンドで照会および設定ができます。 以下を使用して、Arch システムの現在のハードウェアクロック時間標準を確認できます。

$ timedatectl | grep local
RTC in local TZ: no


ハードウェアクロックは timedatectl コマンドで尋ねたり設定できます。ハードウェアクロックの時刻系を localtime に変更するには次を実行してください:

# timedatectl set-local-rtc true

ハードウェアクロックの時刻系を localtime に変更するには、次を実行してください:

# timedatectl set-local-rtc 1

逆にハードウェアクロックの時刻系を UTC に戻すには次を実行してください:

# timedatectl set-local-rtc 0

これらは /etc/adjtime を自動的に生成し、それに応じて RTC を更新します。これ以上の設定は必要ありません。

カーネルの起動中、RTC ドライバーがロードされた時点で、ハードウェアクロックからシステムクロックを設定することができます。設定するかどうかはハードウェアプラットフォーム、カーネルのバージョン・ビルドオプション次第です。設定される場合、ブートシーケンスで既に、ハードウェアクロックは UTC と認識され /sys/class/rtc/rtcN/hctosys (N=0,1,2,..) の値は 1 に設定されます。その後、/etc/adjtime の値を使って、再度 systemd によってハードウェアクロックからシステムクロックが設定されます。そのため、ハードウェアクロックで localtime を使っているとブートシーケンス中に予期しない動作が発生するかもしれません。例えば、システム時刻が後戻りするなど。従ってこの設定は良いアイデアとは言えません。

その後、/etc/adjtime の値に応じて、systemd によってハードウェアクロックからシステムクロックが再度設定されます。したがって、ハードウェアクロックで localtime を使用すると、ブートシーケンス中に予期しない動作が発生する可能性があります。たとえば、システム時間が逆行することは、常に悪い考えです (他にもたくさんあります)。ハードウェアクロックが UTC に設定されていてローカルタイムゾーンについてカーネルに通知しないでください。その結果、Linux システムが使用する FAT ファイルシステムのタイムスタンプは UTC になります。

ノート:
  • timedatectl を使うには D-Bus が有効になっている必要があります。そのため、(インストール中など) chroot 下でこのコマンドが使えないかもしれません。そのような場合には、hwclock コマンドを使って下さい。
  • /etc/adjtime が存在しない場合、systemd はハードウェアクロックが UTC に設定されていると認識しています。

Windows で UTC を使う

RTC を localtime に設定する理由に Windows とのデュアルブートをするためということがあります (Windows は localtime を使っています)。しかしながら、Windows ではレジストリを編集することで RTC で UTC を使っていても対応できるようにすることができます。従って、Linux に localtime を使わせるよりも Windows に UTC を使わせるようにすることが推奨されます。Windows に UTC を使わせる場合、Windows のインターネット時刻機能をオフにするようにしてください。オフにすると Windows はハードウェアクロックにメスを入れなくなるので、代わりに NTP デーモンを使って RTC を同期させる必要があります。

regedit を使って、レジストリに十六進数で 1DWORD 値を追加してください:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation\RealTimeIsUniversal

管理者権限で開いたコマンドプロンプトで以下のコマンドを実行することでも設定できます:

reg add "HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\TimeZoneInformation" /v RealTimeIsUniversal /d 1 /t REG_DWORD /f

もしくは、以下の内容で *.reg ファイルを (デスクトップに) 作成しそれをダブルクリックしてレジストリにインポートしてください:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation]
     "RealTimeIsUniversal"=dword:00000001
ノート: 64ビット版の Windows を使っている場合で、上記の設定を行っても効果がないときは DWORD の代わりに QWORD を使うことで問題が解決することがあります。

DST が変わったことで Windows が時計を更新すると行ってきた場合は、それに従って下さい。Windows は時計を UTC のままにしておき、表示する時間だけ修正します。

値を設定した後にハードウェアクロックとシステムクロックの時刻を更新する必要があるかもしれません。

時計がずれる問題が発生している場合、tzdata を再インストールしてタイムゾーンをもう一度設定してみてください:

# pacman -S tzdata
# timedatectl set-timezone Asia/Tokyo

Ubuntu で UTC を使う

Ubuntu とその派生ディストリはインストール時に Windows が認識されたときにハードウェアクロックを "localtime" と認識されるように設定します。Linux 初心者が Windows コンピュータで Ubuntu を試したときにレジストリを編集しなくてもよいように故意にこのような挙動となっています。

タイムゾーン

現在のゾーンを確認するには:

$ timedatectl status

利用可能なゾーンを一覧するには:

$ timedatectl list-timezones

タイムゾーンを変更するには:

# timedatectl set-timezone <Zone>/<SubZone>

例:

# timedatectl set-timezone Asia/Tokyo

このコマンドによって /usr/share/zoneinfo/ 下の zoneinfo ファイルを指し示したシンボリックリンク /etc/localtime が作られます。リンクを手動で作成する場合 (chroot の中で timedatectl が使用できない場合など)、archlinux(7) に書かれているように、ハードリンクではなくシンボリックリンクを使ってください:

# ln -sf /usr/share/zoneinfo/Zone/SubZone /etc/localtime

詳細は timedatectl(1), localtime(5), archlinux(7) を見てください。

ノート: systemd 以前の設定ファイル /etc/timezone がシステムにまだ存在している場合、もう使われていないので削除しても問題ありません。
ヒント: tzselect を使ってインタラクティブにタイムゾーンを選択することもできます。

地理情報を元に設定

IP アドレスの位置情報を元に自動的にタイムゾーンを設定したい場合、$ curl https://ipapi.co/timezone などで geolocation API を使ってタイムゾーンを取得して timedatectl set-timezone に出力を渡すことで自動設定できます。以下のサービスが無料あるいは一部無料で geo-IP API を提供しています:

また、tzupdateAUR ツールは IP アドレスの位置情報を元にタイムゾーンを自動設定します。

NetworkManager がネットワークに接続するたびにタイムゾーンを更新する

NetworkManager dispatcher スクリプト を作成します:

/etc/NetworkManager/dispatcher.d/09-timezone
#!/bin/sh
case "$2" in
    up)
        timedatectl set-timezone "$(curl --fail https://ipapi.co/timezone)"
    ;;
esac
ヒント: up の代わりに connectivity-change を使用すると、OpenConnect などのクライアントで VPN に接続するときにタイムゾーンの変更を防ぐことができます。

あるいは、ツール tzupdateAUR が IP アドレスのジオロケーションに基づいてタイムゾーンを自動的に設定します。この 最も人気のある IP 地理位置情報 API の比較 は、プロダクションでどの API を使うか決める際に役に立つかもしれません。

クロックスキュー

全ての時計は本当の時間 (一番正確なのは国際原子時) とは違う値を示しています、どの時計も完全ではありません。クォーツを使っている電子時計は(不完全な)時間を刻んでいますが、規則的なズレを生じさせています。この本質的な'ズレ'は'クロックスキュー'や'クロックドリフト'として知られています。

ハードウェアクロックが hwclock で設定された時、新しいドリフト値(一日に何秒ズレるか)が算定されます。このドリフト値は新しく設定された値と以前に設定されていたハードウェアクロックの値の差から計算され、以前のドリフト値とハードウェアクロックが最後に設定された時間を考慮しています。新しいドリフト値と時計が設定された時刻は /etc/adjtime ファイルに書き込まれ以前の値を上書きします。これにより hwclock --adjust を実行することでハードウェアクロックのずれを調整できるようになっています。また、hwclock デーモンが有効になっている場合シャットダウン時にも実行されます (よって systemd を使っているシステムでは実行されません)。

ノート: 以前に設定した時から24時間以内に再度 hwlock が設定された場合、hwclock は経過時間が短すぎて正確にドリフトを計算できないとしてドリフトは再計算されません。

ハードウェアクロックが時間の消失と取得を何度も繰り返している場合、不正なドリフトが保存されている可能性があります (ただし hwclock デーモンが実行中の場合に限ります)。これはハードウェアクロックの時間を間違って設定したり時刻系を Windows や Mac OS と合わせていないときに起こります。/etc/adjtime を削除してドリフト値を削除してから、正しいハードウェアとシステムクロックの時間を設定して、時刻系が直ったか確認してください。

ノート: systemd を使用しているのに /etc/adjtime に保存されているドリフト値を使いたい (つまり NTP を使えない・使いたくない) 場合、定期的に hwclock --adjust を実行するか、それを代わりにする cron ジョブを作って下さい。

ソフトウェアクロックはかなり正確ですが、他の時計と同じく完全に正しいわけではありませんし同じようにズレが起こります。稀に、カーネルが割り込みを飛ばしたときにシステム時刻が正確さを失うことがあります。ソフトウェアクロックの正確性を改善するツールが複数存在します。#時刻同期を見てください。

時刻同期

Network Time Protocol (NTP) はパケット交換でデータの遅延時間が不確定なネットワークを介してコンピュータシステムの時刻を同期するためのプロトコルです。NTP の実装は以下が存在します:

  • Chrony — ローミングフレンドリーで、常時オンラインではないシステムのために特別に設計されたクライアントとサーバーです。ほとんどの場合、ntpd よりも速く、より参照に近い形で収束します。
https://chrony.tuxfamily.org/ || chrony
  • Network Time Protocol daemon — プロトコルのリファレンス実装であり、特に時刻サーバーでの使用が推奨されます。NTPd は割り込みの周期や1秒辺りのティックの数を調整してシステムクロックのずれを減らすことも可能です。NTPd の実行中は11分ごとにハードウェアクロックの再同期も行われます。
http://www.ntp.org/ || ntp
  • NTPsec — NTPd のフォークで、セキュリティに重点を置いています。多くの古いコードが捨てられる以外は、同じように動作します。
https://ntpsec.org/ || ntpsecAUR

適切な NTP ノード以下の機能を持つものは、SNTP("Sinplified" の意)とみなされます。基本的な SNTP クライアントは、長期的なドリフトを追跡することなく、単に 1 つのサーバーから時刻を取得し、すぐに設定することができます。SNTP は精度が低いですが、より少ないリソースで動作します。この精度は通常、デスクトップユーザーや組み込みワークロードには十分ですが、NTP サーバーには受け入れられません。以下は、SNTP を実装しています:

  • ConnMan — A lightweight network manager with SNTP support.
https://01.org/connman (waybackmachine) || connman
  • ntpclient — シンプルなコマンドライン NTP クライアント。
http://doolittle.icarus.com/ntpclient/ || ntpclientAUR
  • OpenNTPD — クライアントとサーバーの両方を実装する OpenBSD プロジェクト。
http://www.openntpd.org/ || openntpd
  • sntp — NTPd に付属している SNTP クライアント。ntpdate を置き換えることができ、サーバー以外の環境での使用が推奨されます。
http://www.ntp.org/ || ntp
  • systemd-timesyncd — クライアント側だけを実装したシンプルな SNTP デーモン。リモートサーバーに時刻を問い合わせることだけを行います。大抵の環境ではクライアントだけで十分です。
https://www.freedesktop.org/wiki/Software/systemd/ || systemd

ユーザー別あるいは一時的に時刻を設定

ときとしてシステムの時刻は変えずに一時的に設定を変えたいということがあるでしょう。例えば、時間を使用するアプリケーションを開発していて実際に動きをテストしたい場合やタイムゾーンが異なる場所からサーバーにログインしている場合などです。

アプリケーションにシステム時刻以外の時刻を使わせたいときは (libfaketime に含まれている) faketime(1) ユーティリティが使えます。

アプリケーションにシステム設定のタイムゾーン以外のタイムゾーンを使わせたいときは、以下のように TZ 環境変数を設定してください:

$ date && export TZ="/usr/share/zoneinfo/Pacific/Fiji" && date
Tue Nov  1 14:34:51 CET 2016
Wed Nov  2 01:34:51 FJT 2016

環境変数によってシステムの時刻が変わるわけではないため、プログラムの開発時に UTC からの時差を変えたり DST をテストすることが可能です。

タイムゾーンを別々に設定するケースとして同一システム上にユーザーが複数存在する場合も考えられます。シェルの設定ファイルで TZ 変数を設定することでユーザーごとにタイムゾーンを設定できます。環境変数#変数の定義自動起動#シェルを参照してください。

ヒントとテクニック

fake-hwclock

alarm-fake-hwclock は RTC をバックアップするバッテリーが搭載されていないシステム用のスクリプトで、シャットダウン時に現在時刻を保存して、起動時に保存した時刻を復元する systemd サービスが付属しています。これによって時刻が飛んでしまうエラーを防ぐことができます。

fake-hwclock-gitAURインストールして fake-hwclock.service起動・有効化してください。

トラブルシューティング

時計が示している値が UTC でも localtime でもない

さまざまな理由が考えられます。例えば、ハードウェアクロックが localtime で動いているのに、timedatectl が UTC に設定されていると、タイムゾーンのオフセットが UTC に二重に適用されることで、localtime でも UTC でもない間違った値になってしまいます。

時計を正しい時刻に直して、ハードウェアクロックに正しい UTC を書き込むには、以下の手順に従って下さい:

  • NTP を設定してください (サービスとして有効にする必要はありません)。
  • タイムゾーンを適切に設定してください。
  • ntpd -qg を実行して手動で時計をネットワークと同期してください、ローカル UTC とネットワーク UTC の時差は無視します。
  • hwclock --systohc を実行して現在のソフトウェア UTC 時刻をハードウェアクロックに書き込んで下さい。

資料