Linux系統時間、系統時區和時鐘同步的部分理解
1、寫在前面因為最近一段時間以來,本人在項目遇到的因為Linux系統時間所引發的問題比較多,所以在此進行總結。
2、Linux系統時間與BIOS硬體時間之間的關係2.1、RTC晶片、i2c總線和BIOS之間的關係實時時鐘(RTC)晶片是普遍應用在集成電路上的一個模塊,採用內置的高精度晶體振蕩器作為時鐘源,在PC和伺服器中,為了保證RTC在主機斷電後還可以繼續保持運轉,整機廠商還會在主板上焊接電池模塊對RTC進行供電。也就是說,對於一個整機設備而言,RTC晶片是一切時間的來源。
i2c總線是集成電路上的一種通信鏈路,連接集成商電路上各個硬體模塊,在本文中主要是用於連接主機(BIOS)和RTC晶片,通常情況下,系統關機時CPU會清空其寄存器,這就導致了設備在再一次啟動時,會通過i2c總線初始化訪問RTC。
粗略的邏輯如下圖所示:
而站在BIOS的角度,實際上是開放了一個i2c接口供上層的作業系統進行調用,以讀取RTC時間,因此本文後文中所闡述的「BIOS時間」,本質上就是BIOS通過i2c總線讀取到的RTC晶片時間。
關於主機(BIOS)通過i2c總線和RTC晶片進行通信和數據傳輸的具體原理涉及集成電路相關知識,站在Linux系統運維的角度,只要了解上述最基本概念即可。
2.2、Linux將BIOS時間視作UTC時間(協調世界時),而Windows則認為BIOS時間就是本地時區的時間Linux系統對於BIOS硬體時間的處理方式與Windows對於BIOS硬體時間的處理是有區別的,Windows和Linux的系統時間在沒有NTP伺服器的情況下,均讀取自BIOS的時間。Windows系統會BIOS時間作為當下本地時區的時間;而Linux系統則會將BIOS時間作為UTC時間(協調世界時),然後根據系統設定的本地時區進行增加或者減少相應的小時數。(如,假使BIOS時間是10:00,且兩個系統的時區都設定為東八區的上海時間,Windows系統會認為10:00就是上海時間,而Linux會在10:00的基礎上增加8個小時,最後認為18:00為上海時間)
Windows和Linux對待BIOS硬體時間不同所造成的最直接的現象在於,在安裝Windows+Linux的雙系統時,兩個系統之間的系統時間會相差8個小時(相對於東八區而言)。而如果想要消除「雙系統8小時時差」這樣的現象,可以在Linux系統上通過「hwclock -w」命令將Linux系統時間和BIOS時間同步為一致,即可解決。
2.3、Linux怎樣更新系統時間Linux系統有兩個時間,一個是系統時間,另一個是BIOS時間。Linux系統在啟動時,會自動讀取BIOS時間作為系統時間,如果讀取不到BIOS時間,則會將上一次成功讀取到BIOS時間作為本次的系統時間,Linux系統成功啟動完成後,假使Linux開啟了時鐘自動同步功能並成功連接到NTP伺服器上,則會將NTP伺服器上的時間作為本機的系統時間。相關流程圖如下所示:
以上流程圖是Linux系統啟動時的流程圖,Linux關機時,還會將系統時間寫入到BIOS時間中,以保持軟硬體時間同步。
3、未安裝ntpdate或chronyc的情況下,Linux如何實現與NTP伺服器時間的同步在很多Linux教材中,談到時間同步的時候,絕大多數都是通過ntpdate命令與安裝有ntpd的時鐘伺服器同步,或者是通過chronyc命令與安裝有chrony的時鐘伺服器同步,但對於客戶端而言,ntpdate和chronyc都不是Linux自帶的時間同步命令,需要額外安裝。而像debian等這樣的Linux發行版,其本身又可以進行時間同步,那這樣的時間同步又是怎樣實現的呢?其實這都歸功於Linux中的systemd-timesyncd.service服務,相關服務可以通過命令「systemctl status systemd-timesyncd.service」命令查看,如果相關的服務為active狀態,說明時間同步服務時開啟的,如下圖所示:
既然有相關服務,就會有相關的配置文件,systemd-timeryncd.service服務的配置文件位於「/etc/systemd」路徑下,文件名稱為「timesyncd.conf」,如下圖所示:
將相關配置文件打開後,我們可以看到內容如下:
按照譯者金步國的博客(http://www.jinbuguo.com/systemd/timesyncd.conf.html#NTP=)針對於timesyncd.conf文件參數欄位的解釋,我們可以獲知到以下信息:
參數欄位
解釋
NTP=
一個空格分隔的NTP伺服器列表, 可以使用主機名,也可以使用IP位址。在運行時, 此處設置的列表將與 systemd-networkd.service(8) 中已配置的NTP伺服器列表合併在一起。systemd-timesyncd 將會依次嘗試列表中的每個NTP伺服器, 直到同步成功為止。如果為此選項設置一個空字符串, 那麼表示清空所有此選項先前已設置的NTP伺服器列表。此選項的默認值為空。
FallbackNTP=
一個空格分隔的NTP伺服器列表,用作備用NTP伺服器。可以使用主機名,也可以使用IP位址。如果所有已配置在 systemd-networkd.service(8) 中的NTP伺服器以及上述 NTP= 中設置的NTP伺服器都嘗試失敗, 那麼將嘗試此處設置的備用NTP伺服器。如果為此選項設置一個空字符串, 那麼表示清空所有此選項先前已設置的NTP伺服器列表。若未設置此選項, 則使用編譯時設置的默認備用NTP伺服器。
RootDistanceMaxSec=
最大可接受的"root distance"秒數(最大誤差)。默認值為 5 秒。
PollIntervalMinSec=, PollIntervalMaxSec=
NTP消息的最小/最大輪詢間隔秒數。PollIntervalMinSec= 必須不小於 16 秒。PollIntervalMaxSec= 必須大於 PollIntervalMinSec= 。PollIntervalMinSec= 默認為 32 秒, PollIntervalMaxSec= 默認為 2048 秒。
NTP欄位後添加了一個NTP地址後(需要刪除前面「#」以取消注釋),通過命令「systemctl restart systemd-timesyncd.service」即可完成與NTP伺服器的時間同步,而不需要額外安裝ntpdate和chronyc工具,如果NTP欄位後的伺服器連接或同步失敗,則會去匹配FallbackNTP欄位後的NTP伺服器。
上述提到,配置文件timesyncd.conf在路徑/etc/systemd下影響時間同步服務的進行,而有的發行版(如deepin V20.2.4),在/etc/systemd目錄下還有一個timesyncd.conf.d文件夾,該文件夾下還有一個配置文件,在deepin系統中,該文件的文件名為deepin.conf,其內容編寫規則與/etc/systemd/timesyncd.conf一致。如果某個Linux發行版和deepin一樣具有/etc/systemd/system.d/timesyncd.conf文件夾,那麼systemd-timesyncd.service服務將優先選擇這個文件夾下的.conf文件作為自己的優先配置文件,而原有的/etc/systemd/timesyncd.conf將作為備用的配置文件,優先級相對較低。
4、Linux系統時區的注意事項4.1、Linux的世界裡,沒有北京時間本章節具體闡述前,我們或許可以這樣說——「Linux的世界裡,實際上不存在北京時間」。
之所以這樣說,是因為Linux系統普遍採用IANA(網際網路數字分配機構)的時區資料庫(Time Zone Database)作為系統的時區。在該資料庫中,中國地區的IANA標準時區有四個——上海、香港、澳門和臺北,因此「北京時間」在Linux系統裡面本質上是沒有的,不過不同的Linux發行版會對這個時區資料庫做修改,如debian系統,增加有「重慶時間」,deepin系統則將中國省份增加得更多,如北京、重慶、成都、西安、南京、烏魯木齊等等,這些時區各對應了一個時區相關文件,位於/usr/share/zoneinfo或/usr/share/zoneinfo/Asia目錄下。而針對於debian、deepin等系統自行修改添加的時區,其本質上是在相應的目錄下創建了一個連結文件指向上海時區的時區文件,畢竟上海時區是IANA規定的標準時區。相關連結文件如下所示(以debian中的重慶時間為例):
當然也有例外,像OpenEuler,則沒有採用連結文件形式指向上海。
4.2、Linux設置時區時應儘可能設置IANA標準時區之所以要將Linux儘可能設置為IANA標準時區,是針對於和涉及到時區相關定製開發Linux軟體而言的。因為全球的Linux發行版有幾百種,並且這些發行版的非IANA標準時區都不同,在不同的開發人員採用不同的Linux發行版當開發環境情況下,會出現他們所開發的軟體沒能適配很多非IANA標準時區,這將導致一些問題——比如某個Linux系統時區為非IANA標準的北京時區,因運行的軟體只適配了IANA標準的上海時間,所以此時軟體內的時間會顯示為UTC時間(數值上等同於零區的格林尼治時間,與北京時間有8小時時差),但系統時間仍舊是正確的北京時間,這會給最終的使用者帶來很不好的體驗。
4.3、典型故障——無論怎樣修改時區,Linux系統始終都顯示零區的格林尼治時間出現這樣的情況一般是因為/usr/share/zoneinfo目錄遭到嚴重破壞造成的,針對這樣的故障,最簡單粗暴的方式就是將找到一套同版本、正常運行的Linux發行版,將其/usr/share/zoneinfo目錄複製出來,對故障Linux系統的相關目錄進行替換。
4.4、典型故障——安全軟體在啟動時強制打開作業系統時間同步功能,後因安全軟體服務端時間錯誤導致時鐘錯誤同步在信創領域,Linux殺毒軟體經常被安裝在Linux電腦上,用於病毒查殺和違規外聯等功能。而主流的Linux殺毒軟體都具有審計功能,審計會產生大量的日誌紀錄,這些紀錄需要有一個時間對應,因此這些殺毒軟體的服務端會自帶時鐘同步,並且會在Linux終端啟動完成後強制打開和配置作業系統的時鐘同步功能,如果殺毒軟體服務端的本地時間時錯誤的,或者說同一個區域網內有多個存在一定時間差的NTP伺服器,將可能會對Linux終端帶來時間上的錯誤。
4.5、典型故障——Linux系統在啟動完成後,時間大約是上一次關機後的時間針對於這樣的故障情況,不要嘗試重啟Linux系統,因為時間出現問題的現象很可能是概率性的,重啟後故障可能就不會復現出來了,所以此時可以按照以下幾個思路進行排查:
(1)通過輸入「date」命令查看系統時間,以及「hwclock --show」命令查看硬體時間,對比兩者是否一致,如果不一致,且顯示出來的硬體時間接近設備上一次關機的時間,則需要檢查硬體主板上相應的供電模塊是否工作正常,以及主板存在多少塊RTC晶片,如果有多塊RTC晶片,就需要查看兩塊RTC晶片的時間是否一致,而如果出現下圖所示的錯誤信息,則代表系統本身無法讀取硬體,則需要進一步排查硬體層面原因,如RTC晶片和i2c總線;(在這裡其實可以不用再排查Linux系統的時鐘驅動了,因為前提是「錯誤時間大約是上一次關機的時間」,說明上次使用時,時間是正常的,正常就代表系統的時鐘驅動本身是可以正常運轉的)
(2)如果需要進一步排查RTC晶片,上述(1)中已經說明需要查看存在多少塊RTC晶片,相關操作方式為——查看/etc/sys/class/rtc目錄下的文件,會出現rtcX形式的文件夾,有多少個這樣文件夾,就說明設備有多少個RTC晶片,我們可以進入rtcX文件夾,並輸入「cat time」命令去查看time文件,如果報出下圖所示錯誤,則說明Linux系統或BIOS之間存在i2c總線層面的通信存在錯誤:
(3)系統通過命令「hwclock --show」讀取硬體時間時,實際上並不是兩塊RTC晶片都會讀取,而是會選擇其中一塊RTC進行讀取,如果讀取到錯誤時間的RTC晶片,則可以手動將系統時間修改正確後,通過「hwclock -w」命令將系統時間寫入硬體後,做後續觀察;
5、擴展補充:協調世界時(UTC)和格林尼治標準時(GMT)的區別格林尼治標準時(GMT),是指英國皇家格林尼治天文臺的標準時間,因地理學上的本初子午線被定義為通過在格林尼治天文臺的經線,因此理論上格林尼治標準時間的正午是指當太陽橫穿本初子午線時的時間。由於地球在其橢圓軌道裡的運動速度不均勻,該時刻可能和實際的太陽時相差16分鐘。加之地球每天的自轉是不規則的,且自轉速度正在緩慢減速。所以,格林尼治時間已經不再被作為標準時間使用,取而代之的是基於國際原子時秒長為基礎的協調世界時(UTC)。
原子時秒的定義:銫-133原子基態的兩個超精細能級間在零磁場下躍遷輻射9,192,631,770周所持續的時間。
目前,UTC被應用在網際網路和全球資訊網標準中,例如NTP(網絡時間協議)就是UTC被使用在網際網路中的一種方式,而日常生活中,在不需要將時間精度控制在秒的情況下,UTC可以被視作和GMT等同。