Network Time Protocol daemon

出自 Arch Linux 中文维基

Network Time Protocol (網絡時間協議)是 GNU/Linux 系統通過互聯網時間伺服器同步系統軟件時鐘的最常見方法。設計時考慮到了各種網絡延遲,通過公共網絡同步時,誤差可以降低到10毫秒以內;通過本地網絡同步時,誤差可以降低到 1 毫秒。

NTP 項目提供了一個名為簡單 NTP 的參考實現。本文介紹如何設置和運行伺服器和客户端 NTP 進程。

安裝[編輯 | 編輯原始碼]

安裝 ntp 軟件包。如果不做任何配置, ntpd 默認工作於客户端模式。如果使用 Arch Linux 默認的配置,請跳轉到 #使用。作為伺服器的配置,請參閱 #NTP 伺服器模式

配置[編輯 | 編輯原始碼]

主要的後台進程是 ntpd, 可以通過 /etc/ntp.conf 配置。詳細信息可以參考手冊 ntp.conf(5) 和相關的 man {ntpd|ntp_auth|ntp_mon|ntp_acc|ntp_clock|ntp_misc}.

連接到 NTP 伺服器[編輯 | 編輯原始碼]

NTP 伺服器通過一個層級系統進行分類,不同的層級稱為 strata;獨立的時間源為stratum 0;直接連接到 stratum 0 的設備為 stratum 1;直接連接到 stratum 1 的源為 stratum 2,以此類推。

伺服器的 stratum 並不能完全等同於它的精度和可靠度。通常的時間同步都使用 stratum 2 伺服器。通過pool.ntp.org 伺服器或這個連結 可以選擇比較近的伺服器池。

下面幾行僅僅是例子:

/etc/ntp.conf
server 0.fr.pool.ntp.org iburst
server 1.fr.pool.ntp.org iburst
server 2.fr.pool.ntp.org iburst
server 3.fr.pool.ntp.org iburst

推薦使用iburst選項,如果第一次嘗試無法建立連接,程序會發送一系列的包。burst 選項則總是發送一系列的包,即使第一次也是這樣。如果沒有明確的允許的話不要使用 burst 選項,有可能被封禁。

NTP 伺服器模式[編輯 | 編輯原始碼]

如果建立一個 NTP 伺服器,你需要添加 local clock 作為一個伺服器,這樣,即便它失去網絡連接,它也可以繼續為網絡提供服務;添加 local clock 作為一個 stratum 10 伺服器 (使用 fudge 命令)這樣它就只會在失去連接時使用本地時鐘:

server 127.127.1.0
fudge  127.127.1.0 stratum 10

下一步,定義規則允許客户端連接你的服務(localhost 也被認為是一個客户端)。使用 restrict 命令;你應該在文件中已經有一行:

restrict default nomodify nopeer noquery

這限制了每個人做任何修改並阻止每個人請求你的時間伺服器狀態:nomodify 防止重新配置你的ntpd(使用ntpqntpdc ),noquery 防止從你的nptd(或是ntpqntpdc)獲取狀態數據。

你也能添加其它選項:

restrict default kod nomodify notrap nopeer noquery
注意: 這會允許其他人查詢你的時間伺服器。你需要添加 noserve 來停止提供時間。

"restrict"選項的完整文檔可以從 ntp.conf(5) 中查找到。詳見 https://support.ntp.org/bin/view/Support/AccessRestrictions

你需要在這一行之後吿訴 ntpd 什麼可以訪問你的伺服器;如果你不是在配置一台 NTP 伺服器的話,下面一行就足夠了。

restrict 127.0.0.1

如果你想要強制DNS解析到IPv6域名,在IP位址或域名前寫上 -6-4 則強制使用IPv4域名),例如:

restrict -6 default kod nomodify notrap nopeer noquery
restrict -6 ::1    # ::1 is the IPv6 equivalent for 127.0.0.1

最後,指定drift文件(它能時刻監控你的時鐘的時間漂移)和log文件的位置:

driftfile /var/lib/ntp/ntp.drift
logfile /var/log/ntp.log

一份基礎的配置文件是這樣的:

/etc/ntp.conf
server 0.pool.ntp.org iburst
server 1.pool.ntp.org iburst
server 2.pool.ntp.org iburst
server 3.pool.ntp.org iburst

restrict default kod nomodify notrap nopeer noquery
restrict -6 default kod nomodify notrap nopeer noquery

restrict 127.0.0.1
restrict -6 ::1  

driftfile /var/lib/ntp/ntp.drift
logfile /var/log/ntp.log
注意: 定義日誌文件不是必須的,但是它對於反饋 ntpd 操作是有好處的。

使用[編輯 | 編輯原始碼]

軟件包默認包含客户端模式的配置,並且使用單獨的用户和羣組,啟動時就會移除 root 權限。如果在終端中啟動,請使用 -u 選項:

# ntpd -u ntp:ntp

systemd 服務默認使用 -u 選項和 -g 選項禁用一個閾值(panic-gate). 這樣即使 ntp-server 的時間和系統時間的差異超過閾值,依然會同步時間。

警吿: 使用 panic-gate 的原因是某些後台任務或服務會引起時間跳躍. 如果系統的時間從來沒有同步過,請考慮先禁用其他服務再進行同步。

兩個服務都依賴系統網絡狀況,會在檢測到網絡連接時開始同步。

啟動時啟用 ntpd[編輯 | 編輯原始碼]

啟用 ntpd.service 服務.

注意: systemd 命令 timedatectl 僅可以控制 systemd-timesyncd, 用 root 執行 timedatectl set-ntp 1 會停止運行中的 ntpd.service.[1]

ntpq 可以查看同步的狀態:

$ ntpq -p

delay, offset 和 jitter 不應該為零,ntpd 同步的伺服器前有星號,ntpd 可能等待很多分鐘後才會進行同步,請等 17 分鐘 (1024 秒).

每次啟動同步一次[編輯 | 編輯原始碼]

另一種方式是 啟用 ntpdate.service 服務,每次啟動都同步一次(-q) 並且是 non-forking (-n), 進程不會在後台運行。如果是伺服器或者很多天才會重啟一次,不建議使用此方式。

如果需要把同步到的時間寫入硬件時鐘,請按照 這裏 的説明修改服務並啟動:

/etc/systemd/system/ntpdate.service.d/hwclock.conf
[Service]
ExecStart=/usr/bin/hwclock -w

技巧[編輯 | 編輯原始碼]

有網絡連接的時候啟動ntpd[編輯 | 編輯原始碼]

ntpd 可以由你的網絡管理器啟動, 所以ntp這個守護進程只有在計算機有網絡連接的時候才會啟動.

Netctl

本文或本節需要翻譯。要貢獻翻譯,請訪問簡體中文翻譯團隊

附註: 英文頁面風格不好。添加 -u 參數以及「使用」中提及的可選參數,或儘可能使用 systemctl 。(在 Talk:Network Time Protocol daemon# 中討論)

給你的 netctl 配置文件添加如下這幾行:

ExecUpPost='/usr/bin/ntpd || true'
ExecDownPre='killall ntpd || true'
NetworkManager

通過網絡管理器的 dispatcher 腳本,可以同網絡連接一起啟動/終止ntpd 守護進程。 安裝networkmanager-dispatcher-ntpdAUR 預配置包 #啟動時啟用 ntpd 來讓網絡連接同步ntp啟動/終止.

KDE

在KDE中,通過右擊時間圖標選擇 Adjust date/time,可以使用 NTP (別忘了安裝NTP)。 注意, 在配置KDE中配置NTP之前,先要把 ntp 守護進程設置為  disabled 狀態. [2]

在GPS中使用NTP[編輯 | 編輯原始碼]

大多數聯網的交通工具要通過(共享內存) 方式讓 ntpd 從GPS中接收時間。 但是, 從 ntpd 4.2.8版本開始,一個 更好 的辦法出現了----直接與 gpsd守護進程交互。這個要先安裝 gpsd .

/etc/ntp.conf 配置文件中添加下面這幾行:

/etc/ntp.conf
#=========================================================
#  GPSD native ntpd driver
#=========================================================
# This driver exists from at least ntp version 4.2.8
# Details at
#   https://www.eecis.udel.edu/~mills/ntp/html/drivers/driver46.html
server 127.127.46.0 
fudge 127.127.46.0 time1 0.0 time2 0.0 refid GPS

只要 gpsd 一直起着,ntp就會一直正常運行。 ntp會通過一個本地套接字同 gpsd 連接, 搜索 gpsd 返回的 "gpsd_json" 對象.

要檢驗安裝的話, 首先要檢查 gpsd 是不是正常運行:

 $ cgps -s 

然後等個幾分鐘運行 ntpq -p. 這個會顯示 ntpd 是否已經跟 gpsd 建立連接了:

$ ntpq -p
remote           refid            st t when poll reach   delay   offset  jitter
 ==================================================================================
*GPSD_JSON(0)    .GPS.            0 l   55   64  377    0.000    2.556  14.109
提示:如果 reach 這列是0的話, 這就説明 ntpd 還沒有同 gpsd 建立連接。 等幾分鐘再試一次。 有時 ntpd 要花點時間來跟gpsd 建立連接。

在 chroot 底下運行[編輯 | 編輯原始碼]

注意: 在試圖把 ntpd 放到chroot目錄下面之前,ntpd 應該在正常路徑下啟動 (默認在 Arch Linux 安裝路徑下)。 因為在相對以root身份運行的進程,chroots的用户相對沒有啥權限的。

創建一個新目錄(如果還沒創建的話) /etc/systemd/system/ntpd.service.d/,並添加在裏面添加文件 customexec.conf ,內容如下:

[Service]
ExecStart=
ExecStart=/usr/bin/ntpd -g -i /var/lib/ntp -u ntp:ntp -p /run/ntpd.pid

然後, 編輯 /etc/ntp.conf 來改變 driftfile 路徑來讓跟它跟 chroot 路徑保持一致, 而不是還用原先的普通路徑。修改

driftfile       /var/lib/ntp/ntp.drift

driftfile       /ntp.drift

通過root創建永久目錄和文件,作為一個合適的 chroot 環境來支持 getaddrinfo() :

# mkdir /var/lib/ntp/etc /var/lib/ntp/lib /var/lib/ntp/proc
# touch /var/lib/ntp/etc/resolv.conf /var/lib/ntp/etc/services

然後通過修改 fstab 綁定前面提到的文件:

/etc/fstab
...
#ntpd chroot mounts
/etc/resolv.conf  /var/lib/ntp/etc/resolv.conf none bind 0 0
/etc/services	  /var/lib/ntp/etc/services none bind 0 0
/lib		  /var/lib/ntp/lib none bind 0 0
/proc		  /var/lib/ntp/proc none bind 0 0
# mount -a

最後, 再一次重啟 ntpd 監控進程。 一旦重啟完成你就可以通過檢查 /proc/{PID}/root 的軟連接來判斷監控進程是不是在 chrooted 下面工作:

# ps -C ntpd | awk '{print $1}' | sed 1d | while read -r PID; do ls -l /proc/$PID/root; done

正常應該連結到 /var/lib/ntp 而不是 /.

不用等一段時間就要確定 driftfile 配置是否工作正常是比較困難的, 因為 ntpd 不會經常讀寫。 如果配置錯誤的話,log裏面會打印一個error; 如果配置正確的話, 時間戳會更新的。 可以通過等一天來判斷,如果沒有log中沒有錯誤打印,並且log的時間戳還更新了,那麼説明配置成功了。

排錯[編輯 | 編輯原始碼]

無法分配請求地址[編輯 | 編輯原始碼]

本文或本節需要翻譯。要貢獻翻譯,請訪問簡體中文翻譯團隊

附註: 英文章不正。對需要或必須使用 IPv6 的用户而言,此方案不可行。(在 Talk:Network Time Protocol daemon# 中討論)

如果收到下列無法分配請求地址的報錯信息:

$ journalctl -u ntpd
ntpd[2130]: bind(21) AF_INET6 fe80::6ef0:49ff:fe51:4946%2#123 flags 0x11 failed: Cannot assign requested address
ntpd[2130]: unable to create socket on eth0 (5) for fe80::6ef0:49ff:fe51:4946%2#123
ntpd[2130]: failed to init interface for address fe80::6ef0:49ff:fe51:4946%2

可以禁用 IPv6 解決。做法是:編輯 ntpd.service 添加 -4 參數:

[Service]
ExecStart=
ExecStart=/usr/bin/ntpd -g -u ntp:ntp -4

參見[編輯 | 編輯原始碼]