【Linux】UTCや時刻関連の仕組みで学んだこと

2021年1月7日

こんにちは、キクです。

本記事ではLinux学習シリーズとして、僕が学んだ内容をアウトプットしていこうと思います。
今回は『UTC』および『時刻関連の仕組み』をテーマに書いていきたいと思います!

それでは、よろしくお願いします。

動作環境

本記事の内容は、下記の環境で実施したものになります。
・CentOS7 on VirtualBox on macOS

注意事項

本記事は僕が経験した内容をもとに記載しておりますが、実行環境や設定内容によっては動作が異なる場合があります。
そのため『参考程度』にお読みいただけますと幸いです。

システムにおける時刻設定の重要性

昨今世界にはたくさんのシステムが存在しています。
それらのシステムにおいては今回のテーマである「時刻設定」は非常に重要な要素であることは言うまでもありませんよね。
時刻情報が使われるケースはさまざまです。

身近なで言えば「ファイルの更新日時」ながとあります。
システム内に多数存在する各ファイルやフォルダは「いつ」作成されたものなのか。
もしシステムの時刻情報がヘンテコな設定になっていたら?
作成日・更新日などが分からず困ってしまいますよね。

またシステムに何かしらの「障害」が発生したとき。
こんなときにはシステムが吐き出した「ログファイル」を頼りに障害の発生日時や原因を追跡していくと思います。
もしシステムの時刻情報がとんちんかんな設定になっていたら?
障害調査が進まず困ってしまいますよね。

ここで上げたのは僅かな例ですが、これだけでもシステムにおいて時刻情報が大切であることがお分かりいただけるかと思います。

UTCとは

ここから時刻関連の内容をいくつかお話しますが、まずはUTCについて触れていきたいと思います。
UTCとはUniversal Time Coordinatedの略で、「協定世界時」と呼ばれるものです。
この「協定世界時」というのは、現在世界の基準となっている時刻(標準時)のことです。
UTCと並ぶ概念で「GMT」と呼ばれるものがあります。

GMTとはGreenwich Mean Timeの略で、「グリニッジ標準時」と呼ばれるものです。
UTCが現在の世界標準時になる以前はGMTが世界の標準時として扱われていました。
切り替わった理由としては、それぞれの時刻算出方法の面でUTCの方がより正確であろうとなったからだそうです。

ちなみにUTCはセシウム原子の振動数をもとに時間を導き出しており、GMTはグリニッジ天文台という場所で天文観測をして時間を導き出しています。
地球の自転の関係で1日の長さが年間を通して一定ではないということも影響してUTCに軍配が上がったとか。
しかし、両者の差異はとても小さいため「UTC=GMT」として扱うこともあるみたいです。

タイムゾーンとは

次にタイムゾーンについて。
タイムゾーンは先述の「UTC」をもとに地域ごとに区分された標準時間帯のこと。

例えば日本(東京)のタイムゾーンは「Asia/Tokyo」として存在しており、「UTC」から9時間進めた時刻になります。
また、タイムゾーンにより地域ごとに区分された標準時のことをローカルタイムと呼びます。
日本(東京)の場合は「JST」です。
UTCがPM13:00の時、JSTは9時間加えたPM22:00という形になります。

ここで少しLinux的なお話。
タイムゾーンの情報は「/usr/share/zoneinfoディレクトリ配下」にバイナリファイルとして格納されています。

[root@centos7 ~]# ls /usr/share/zoneinfo
Africa		Chile		GB		Indian		Mexico		posixrules	Universal
America		CST6CDT		GB-Eire		Iran		MST		PRC		US
Antarctica	Cuba		GMT		iso3166.tab	MST7MDT		PST8PDT		UTC
Arctic		EET		GMT0		Israel		Navajo		right		WET
Asia		Egypt		GMT-0		Jamaica		NZ		ROC		W-SU
Atlantic	Eire		GMT+0		Japan		NZ-CHAT		ROK		zone1970.tab
Australia	EST		Greenwich	Kwajalein	Pacific		Singapore	zone.tab
Brazil		EST5EDT		Hongkong	leapseconds	Poland		Turkey		Zulu
Canada		Etc		HST		Libya		Portugal	tzdata.zi
CET		Europe		Iceland		MET		posix		UCT

そしてシステムで利用するタイムゾーンは上記のファイルを「/etc/localtimeファイル」にコピーまたはシンボリックを作成して設定します。

例えばシンボリックリンクで作成されている場合は以下のように確認することができます。

[root@centos7 ~]# ls -l /etc/localtime
lrwxrwxrwx. 1 root root 32 Nov 30 2020	/etc/localtime -> ../usr.share/zoneinfo/Asia/Tokyo

この結果から、タイムゾーンは「日本」に設定されていることが分かります。

システムクロックについて

続いてシステムクロックについて。
システムクロックはOSが管理している時計のことです。
先述した「ファイルの更新日時」などはこのシステムクロックを利用しています。
この時計はメモリ上に置かれています。
そのため、電源を落としたらリセットされます。

ではリセットされた時計はどのように設定すればよいのか。
基本的にはOS起動のタイミングで後述の「ハードウェアクロック」を参照してセットされます。
なお、システムクロックは「UTC」で運用・管理されます。
そして設定したタイムゾーンの差異を反映した時刻がシステムで利用されます。

timedatectlコマンドが便利だった話

timedatectlというコマンドを実行した結果が個人的に内容がスッと入ってきたのでご紹介します。

[root@centos7 ~]# timedatectl status
	     Local time: Wed 2021-01-06 20:18:22 JST
	 Universal time: Wed 2021-01-06 11:18:22 UTC
	       RTC time: Wed 2021-01-06 11:18:19
	      Time zone: Asia/Tokyo (JST, +0900)
	    NTP enabled: yes
      NTP synchronized: no
	RTC in local TZ: no
            DST active: n/a

上記実行結果の「Universal time」という項目が「システムクロック」になります。
右端に「UTC」と表示されていることからもシステムクロックがUTCであることが分かります。
その上の「Local time」はそのまま「ローカルタイム」のことです。
この環境ではタイムゾーンとして「日本」を設定しているので「UTC+9時間」の時刻になっています。

ハードウェアクロックについて

次はハードウェアクロックについて。
ハードウェアクロックはその名の通りハードウェア上に実装された時計になります。
先程のシステムクロックはメモリ上で稼働していたため電源を落とすとリセットされていましたが、
こちらのハードウェアクロックは電源を落としても稼働し続けることができます。
1時間電源を落としてから起動しても、時刻情報は1時間後のものになっています。

ハードウェアクロックの運用・管理方法は「UTC」または「ローカルタイム」の2パターンあります。
システムクロックはOS起動時にハードウェアクロックを参照して時刻をセットするとお話しましたが、
この2パターンの設定内容により動作が異なります。
ハードウェアクロックが「UTC」の場合には、システムクロックも「UTC」なのでそのままセットすることができます。

しかし、ハードウェアクロックが「ローカルタイム」の場合には、システムクロックにセットする際には設定したタイムゾーン分の時刻を考慮してセットされます。
ややこしいのでローカルタイム「JST」を例にもう少し詳しく書いていきます。
JSTは「UTC+9」の時刻でした。
ハードウェアクロックが「ローカルタイム」で設定されている場合には最初からJSTがハードウェアクロックにセットされます。
「JST=UTC+9」は「JST-9=UTC」でもあるので、システムクロックには「UTC」すなわち「JST-9」がセットされれば辻褄が合います。
システムクロックのお話でも登場したtimedatectlコマンドを使って比較してみます。

ハードウェアクロック=UTC

まず「ハードウェアクロック=UTC」の場合。

[root@centos7 ~]# timedatectl status
	     Local time: Wed 2021-01-06 20:18:22 JST
	 Universal time: Wed 2021-01-06 11:18:22 UTC
	       RTC time: Wed 2021-01-06 11:18:19
	      Time zone: Asia/Tokyo (JST, +0900)
	    NTP enabled: yes
      NTP synchronized: no
	RTC in local TZ: no
            DST active: n/a 

「RTC time」がハードウェアクロックを表しています。
システムクロック(Universal time)がUTCなので、その時刻と(ほぼ)一致していることからもハードウェアクロックがUTCであることが分かります。
これであればシステムクロックはOS起動時にハードウェアクロックの時刻をそのままセットすればいいことになります。

ハードウェアクロック=ローカルタイム

次に「ハードウェアクロック=ローカルタイム」の場合。

[root@centos7 ~]# timedatectl status
	     Local time: Wed 2021-01-06 20:18:22 JST
	 Universal time: Wed 2021-01-06 11:18:22 UTC
	       RTC time: Wed 2021-01-06 20:18:22
	      Time zone: Asia/Tokyo (JST, +0900)
	    NTP enabled: yes
      NTP synchronized: no
	RTC in local TZ: yes
            DST active: n/a

ここでは「RTC in local TZ」という項目が「yes」になっています。
これが「ハードウェアクロック=ローカルタイム」であることを判断する1つの材料になります。

また「Local time」が「RTC time」と一致していることからもハードウェアクロックがローカルタイムで動いていることが分かりますね。
そしてシステムクロック(Universal time)がハードウェアクロック(RTC time)から9時間前の時刻になっていることも分かるかと思います。
システムクロックはOS起動時にハードウェアクロックの時刻を参照するのでした。
そのためハードウェアクロックがローカルタイム(JST)の場合にはUTCであるシステムクロックは-9時間にしてあげないと辻褄が合いません。
この実行結果からもちゃんと時刻調整ができていることが読み取れます。

ハードウェアクロックを「ローカルタイム」とした場合にはどこからその時刻情報を持ってくるのかということについてですが、
この情報は「環境変数TZ」あるいは「/etc/localtimeファイル」から取得することになります。

NTPサーバについて

ここまでで「システムクロック」と「ハードウェアクロック」について簡単にお話しました。
これら2つに共通して言えることは「精度が優れているとは言い難い」ということです。
システムクロックは電源を落としたらリセットされてしまいますし、ハードウェアクロックもマザーボード内臓の電池が消耗されていくにつれて時計が狂ってきてしまうそうです。
そんな悩みを解決してくれるのが「NTPサーバ」です。

NTPとはNetwork Time Protocolの略で、ネットワークに接続されたコンピュータや各種機器の時刻同期に用いられるプロトコルのことです。
つまりNTPサーバとは時刻サービスを提供するサーバになります。
システムクロックやハードウェアクロックは自身の内部的なお話でしたが、NTPサーバを用いることで自身とは別の外部から時刻情報を取得して時計をセットする形になります。

ちなみにNTPサーバの情報を用いてセットするのは「システムクロック」になります。
同期した「システムクロック」から必要に応じて「ハードウェアクロック」にも同期をかけたりもします。
また、NTPサーバは階層構造になっていて最上位は「原子時計」や「GPS」などです。
この階層構造を利用して、NTPサーバは自分より上位のNTPサーバから正確な時刻を取得しています。
そして現在世界中で稼働する多くのシステムがNTPサーバから時刻情報の同期を実施して時刻合わせをしています。
今回NTPサーバについては深堀りはしませんが、今日のシステムにおいてNTPサーバがなくてはならない存在であることは間違いありません。

おわりに

いかがだったでしょうか。

「システムクロック」「ハードウェアクロック」「NTPサーバ」などさまざまな時計の仕組みがありましたね。
僕も本記事を書くことを通して、改めて...というより更に深く理解することができました。
システムにおいて正確性が求められる「時刻情報」。
何かあったときに仕組みを理解していることはとても重要ですよね。
本記事が少しでもその理解のお役に立てれば嬉しいです!
・・・いい機会なのでNTPサーバについてもより深く勉強してみようかな🤔

本記事を最後まで読んでいただき、ありがとうございました。
ではでは!

-Linux
-