⚠️ 提示:本站 AI 助手使用博主个人 API Token,没事别特么瞎用。
运维 · · 约 49 分钟阅读

NTP 时间服务完全指南:chronyd 与 ntpd 自建内网服务器、客户端跨平台配置、以及常用命令与排障

时间不准=证书过期=Kerberos 全炸=HDFS/HBase 数据块错乱=分布式 trace 全拼不上,公司到几十台机器就该自建内网 NTP。本文从 stratum 层级与 UDP 123 基础开始,先给 chronyd vs ntpd 一份《场景+优缺点+性能差》对比表告诉新环境选谁,再分别讲 chrony(RHEL 7+/Ubuntu 18.04+ 默认)与 ntpd 两套从 0→1 搭内网服务器的完整配置,客户端覆盖 Linux chrony / systemd-timesyncd / Windows w32tm / macOS / 旧 ntpd,最后把 chronyc / ntpq / timedatectl / hwclock 常用命令与 8 个高频坑(reach 0、虚拟机跳时、时区 UTC、离线恢复慢、stratum 16、RTC 与系统时钟不同步…)全部列好示例。

NTP 时间服务完全指南:chronyd 与 ntpd 自建内网服务器、客户端跨平台配置、以及常用命令与排障

适用:CentOS 7 / RHEL 7 8 9 / Rocky / AlmaLinux、Ubuntu 18.0424.04、Debian 1012、Windows Server 2016~2025 / Win10/11、macOS 12+。


一. 前置概念:时间为什么重要 + NTP stratum 层级 + 常见名词

0.1 为什么公司过了 10 台机器就必须自建内网 NTP

时间不准是那种”平时没事,一出就是爆炸级事故”的基础设施:

  • Kerberos / AD / LDAP:时间差超过 5 分钟(KDC 默认 clock_skew)就直接拒绝登录,全公司上不了域
  • JWT / SSL / 代码签名证书:证书的 notBefore / notAfter 是按本机时间比的,时钟差几个月浏览器全报 ERR_CERT_DATE_INVALID
  • HDFS / HBase / Ceph / etcd / Consul:要求集群节点间时间差 < 100ms,差太多 HDFS 会以为数据块过期、etcd 选主乱跳、Ceph OSD 反复 down
  • 分布式链路追踪 / 日志:ELK / Jaeger / Prometheus 都靠 @timestamp 串,节点间差 1 秒 trace 直接拼不上、告警全乱序
  • 数据库双写 / Kafka exactly-once:用 wall clock 做幂等判断的业务,差 5 秒可能出现丢单或重复扣款
  • 安全审计:等保 2.0 要求日志时间戳误差 < 1 秒、要有可信时间源

0.2 NTP 基础:stratum(层级)1~16

flowchart TB
  S0["Stratum 0<br/>原子钟 / GPS / 北斗 / 铯钟(真实时钟源,不是网络节点)"]
  S1["Stratum 1<br/>NTP 一级源服务器(直连 Stratum 0)"]
  S2["Stratum 2<br/>公司内网 NTP 主服务器(对 S1 同步)<br/>← 我们要搭的"]
  S3A["Stratum 3<br/>业务服务器"]
  S3B["Stratum 3 ...<br/>办公电脑 / 交换机"]
  S0 -->|"串口 / PPS / USB 直连"| S1
  S1 -->|"UDP 123 同步"| S2
  S2 -->|"对下给几百 ~ 几千台"| S3A
  S2 -->|"对下给几百 ~ 几千台"| S3B
  • Stratum 0:真实时钟源,不出现在 NTP 协议里
  • Stratum 16:表示”这个服务器根本没同步成功,不可信任”。客户端 chronyc sources 看到 Stratum=16 → 当它不存在
  • 经验值:内网服务器建议选 4~7 个上游 S1/S2(数量太少不稳定、太多浪费带宽)。国内公开一级和二级 S2 在 §3.1 里列了。

0.3 时间系统里的”几对兄弟概念”

术语意思命令看它
系统时钟 (System Clock)Linux 内核维护的软时钟,开机后所有程序读的就是它date / timedatectl
硬件时钟 (RTC / Hardware Clock)主板电池驱动,关机走它hwclock -r / timedatectl 里 RTC time
TAI / UTC / 本地时 / 时区UTC=不含闰秒的国际原子时+累计闰秒偏移;本地时=UTC+时区偏移timedatectl list-timezones / TZ=Asia/Shanghai date
NTP 同步 vs 手动调时间同步是”慢慢拉回”(slew);手动调是”突然跳一下”(step)。生产 step 会把连续日志戳出洞,尽量用 NTP 慢慢拉。chrony 的 makestep 控制 step/slew 阈值

二. chronyd vs ntpd 深度对比表(选哪个直接看这里)

一句话结论:所有新部署 95% 直接选 chronyd。 只有「你要对接的嵌入式设备/老交换机只支持老 NTP v3 变种 + 有一堆祖传 ntpd 脚本」才守 ntpd。

维度chronyd(默认推荐)ntpd(经典 ntp.org 实现)
发布 / 维护者2012 年 Miroslav Lichvar 新写,活跃维护中1980s 起的 ntp.org 参考实现,代码量大、bug 出得慢但出了大
RHEL/CentOS 默认RHEL 7+ / Rocky / Alma 默认RHEL 6 及以前默认
Ubuntu 默认Ubuntu 18.04+ 默认(之前用 ntpdate + ntp)Ubuntu 16.04 及以前默认
虚拟机/离线恢复速度 ⭐优秀:启动后用 iburst 连发 8 包,数秒内拿到首个样本;离线很久恢复后通常 10~30 秒收敛到 <100ms一般:首次冷启动至少 1 分钟;长时间断网后恢复要 5~15 分钟,还有可能卡住不更新
对抖动网络 / 非对称延迟的补偿自带更好的算法(频率跟踪模型更简单、稳定),无线/跨公网更准也行,但默认配置在坏网络下鲁棒性比 chrony 差
精度现代机器局域网内都能跑到 ±100us 级,肉眼没差;局域网 chrony 通常略好(更少干扰)一样准(NTP 精度瓶颈主要是网络+硬件 PPS,不是实现)
最小上游数pool/server 随便写 2 个也能跑,有 local stratum 10 做兜底4~7 个官方起步;少于 4 个可能”找不到 consensus”拒绝 step
系统无网/无上游时支持 local stratum 10 与孤立模式(orphan mode)——断外网也能继续用自己的时钟给内网提供一个统一时间也支持 orphan,但配置更啰嗦
RTC / 硬件时钟同步rtcsync 指令直接开启,每 11 分钟把系统时间刷到 RTC;关机时也刷要用额外 hwclock cron 或 -A 参数
配置文件语法/etc/chrony.conf / /etc/chrony/chrony.conf:短小直白,~15 行够用/etc/ntp.conf:restrict 权限语法稍复杂,小白容易写错
管理命令chronyc(交互式+子命令,有 help)ntpq / ntpdc / ntpstat 三件套(ntpdc 在新版已不推荐)
监控/导出指标chronyc tracking / sources / sourcestats 直出 JSON-like 文本;社区有 chrony_exporter 给 Prometheus要写脚本解析 ntpq -pn,没 chrony 直观
漂移文件driftfile /var/lib/chrony/drift 一个文件搞定driftfile /var/lib/ntp/drift + 一堆 stats 文件(statsdir)
安全扩展(NTS / Network Time Security)chrony 4.0+ 支持 NTS over TLS(时间也能不被中间人污染)主分支进展慢,NTS 还没正式合入
额外功能给 VMs 用 autoselect、对 PTP 硬件时间戳支持更好、leapsectz 直接读 tzdata 的闰秒老而全,支持 broadcast/multicast 自动发现
适合的场景云主机 / 笔记本 VM / 办公笔记本休眠唤醒 / 网络抖动环境 / 新部署 95%真·物理机房+GPS/PPS 直连原子钟 + 一堆老脚本不动
端口客户端:UDP 123 出方向(发请求);服务端:UDP 123 入方向(对外答)。chronyd 额外 Unix Socket /var/run/chrony/chronyd.sock 给本机 chronyc 用同左,管理走 ntpq 也用 UDP 123 特殊模式包

三. 场景快速结论

你的场景选哪个服务端?选哪个客户端?
新机房 100 台以内、CentOS 7+/Ubuntu 20.04+✅ chronyd✅ chrony(和服务端同包,省得装两个)
要跟 S350/老 Cisco Catalyst 3560 的 NTP v3 对时chronyd(它兼容 NTP v3/v4 协议,默认 v4 自动协商)老设备照旧
有 GPS / PPS / 原子钟直连机器做 Stratum 1chronyd 或 ntpd 都行,老运维选 ntpd 更熟chrony
纯 Windows AD 环境✅ 直接让 PDC 模拟器角色 DC 对外对时,域内机器自动跟 DC(不用另搭 Linux NTP)域控 / w32tm
笔记本 / 经常休眠的 VM / 无线办公机✅ chrony(休眠唤醒秒级同步回来)✅ chrony
嵌入式 tiny Linux 只有 8M Flashchrony 更轻量(~500KB vs ntpd ~2MB)chrony

四. 方案 A:chronyd 自建内网 NTP(推荐)

以 RHEL 系(CentOS/Rocky/Alma)路径为主,括号里是 Debian/Ubuntu 的路径差异。Ubuntu 22.04 实测全通。

3.1 选上游服务器(给你的 NTP 对时的”老大哥们”)

不建议直接指向 pool.ntp.org 这种动态 RR,建议写 4~7 个固定 FQDN 并加 iburst。国内常用稳定源:

# 中国 NTP 联盟(edu 背景,Stratum 1/2,非常稳)
server ntp.ntsc.ac.cn iburst
server ntp.aliyun.com iburst
server ntp1.aliyun.com iburst
server ntp.tencent.com iburst
server time1.cloud.tencent.com iburst
# 国内教育网备选
server s2a.time.edu.cn iburst
# 国际兜底(放最后,没国内的优先)
server time.cloudflare.com iburst

阿里云 ntp.aliyun.com/ntp1~7.aliyun.com、腾讯 ntp.tencent.com/time1~5.cloud.tencent.com、Cloudflare time.cloudflare.com(全球 Anycast,回国也还行)。

3.2 安装 + 开机启动

# ---- RHEL 系(CentOS 7-9 / Rocky / Alma)----
sudo dnf install -y chrony
sudo systemctl enable --now chronyd
sudo systemctl status chronyd   # 看 active (running)

# ---- Debian / Ubuntu 18.04+ ----
sudo apt install -y chrony
sudo systemctl enable --now chrony

chrony 配置文件路径:

  • RHEL 系:/etc/chrony.conf
  • Debian/Ubuntu:/etc/chrony/chrony.conf

3.3 一份可直接抄的 chrony 服务端配置(含关键字解释)

# ---- RHEL 系:覆盖 /etc/chrony.conf ----
cat | sudo tee /etc/chrony.conf > /dev/null <<'EOF'
# ========== 1. 上游服务器(写 4~7 个,iburst 启动时 4 秒打 8 包快速同步)==========
pool 2.centos.pool.ntp.org     iburst maxsources 4
server ntp.aliyun.com          iburst
server ntp1.aliyun.com         iburst
server ntp.tencent.com         iburst
server time.cloudflare.com     iburst prefer
server ntp.ntsc.ac.cn          iburst

# ========== 2. 漂移文件:记录本机晶振偏频,重启后不用重新学习 ==========
driftfile /var/lib/chrony/drift

# ========== 3. makestep 跳时阈值:仅前 3 次更新、若误差 > 1 秒才硬 step,之后一律慢慢 slew ==========
# 虚拟机/新机器首次开机时间差经常有好几小时,不做 makestep 要几个星期才能拉回
makestep 1.0 3

# ========== 4. rtcsync:每 11 分钟把系统时钟刷回主板 RTC,断电不丢 ==========
rtcsync

# ========== 5. 给内核用 PPS/硬件时间戳(带 GPS 卡才打开,普通物理机可注释)==========
# hwtimestamp eth0 minpoll 2

# ========== 6. 允许内网哪些网段来问我(allow 一行一段,写最精确的 CIDR)==========
# 公司内网 VLAN
allow 10.0.0.0/8
allow 172.16.0.0/12
allow 192.168.0.0/16
# 办公 WiFi
allow 100.64.0.0/10
# 别写 allow 0.0.0.0/0 ::/0,会被当成开放反射打 DDoS

# ========== 7. 孤立模式:外网全断时,我仍用 local 时钟作为 stratum 10 对外答 ==========
# 这样即使断外网,全公司几百台机器也会"互相同步到同一个时间"(只是不准 UTC,但至少是统一的)
local stratum 10 orphan

# ========== 8. 密钥 / NTS / 认证(默认 keyfile,没 NTS 需求就这样)==========
keyfile /etc/chrony.keys
# 开启 NTS(NTP over TLS,防中间人,chrony 4.0+,需要证书)
# ntsserver cert /etc/pki/chrony/ntp.crt key /etc/pki/chrony/ntp.key
# ntsserver port 4460

# ========== 9. 闰秒:直接读系统 tzdata,不用自己下 leap-seconds.list ==========
leapsectz right/UTC

# ========== 10. 日志(出问题好回查;正常跑可以关掉省 I/O)==========
logdir /var/log/chrony
log tracking measurements statistics
EOF

Debian/Ubuntu 版文件放 /etc/chrony/chrony.conf,其余内容 100% 通用,driftfile 路径换成 /var/lib/chrony/chrony.drift 即可。

关键字释义速查:

指令含义注意事项
pool xxx iburst maxsources N从一个 DNS RR 池里挑 N 台iburst = 启动时 4 秒打 8 包快速收敛,建议每个 server/pool 都加
server xxx iburst prefer指向单个服务器;prefer 表示其他条件相同时优先选这台别给太多 prefer,一个就行
driftfile <path>保存本机晶振偏频(PPM)路径所在目录必须可写,chrony 用户权限
makestep <阈值> <N>启动前 N 次更新时误差>阈值就硬 step,之后慢慢 slew1.0 3 是最佳实践,调太小会 step 太频繁
rtcsync每 11 分钟把系统时钟刷 RTC有 VM 会关 RTC,没效果但无害
allow <CIDR>允许哪些 IP 段来请求你(服务端必加)小白最容易忘 → 客户端永远 REACH=0
local stratum 10 orphan当所有上游挂了,我对外宣称 stratum 10一定加!断外网不至于全公司时钟各奔东西
hwtimestamp <if>启用网卡硬件时间戳物理机千兆网卡普遍支持,精度从 ms 级到 us 级
leapsectz right/UTC自动处理闰秒需要系统有 right/ 时区数据(glibc 都带)
log tracking measurements statistics三档日志;measurements 每个样本都写,一天几十 MB排障完可以关掉

3.4 开防火墙 + SELinux

# ===== firewalld(RHEL 系默认)=====
sudo firewall-cmd --permanent --add-service=ntp      # NTP 协议=UDP 123
sudo firewall-cmd --reload
sudo firewall-cmd --list-services                     # 看到 ntp 就对了

# ===== ufw(Ubuntu / Debian 默认)=====
sudo ufw allow from 10.0.0.0/8         to any port 123 proto udp comment 'NTP from Corp LAN'
sudo ufw allow from 172.16.0.0/12      to any port 123 proto udp
sudo ufw allow from 192.168.0.0/16     to any port 123 proto udp
sudo ufw reload

# ===== SELinux(RHEL 系):chronyd 端口默认就在策略里,一般不用额外动作,确认一下 =====
sestatus | head -3
sudo ausearch -m avc -ts recent   # 空的就 OK

3.5 重启 chronyd + 三条验收命令

sudo systemctl restart chronyd
sleep 6

# ===== 验收 1:sources(选了哪些源、状态如何)=====
chronyc sources -v
# 关键列:
#   S(状态) = ^ 服务器 / = pool / # 本地RTC / ? 不可达
#   State = * 正在跟它同步 / + 是健康候选 / - 健康但被淘汰 / ? 不可达 / x 假时间(falseticker)
#   LastRx = 距上次收到回复多久(秒),理想 32~1024
#   Reach = 8 位十六进制,'377' 表示最近 8 次请求全收到回包(⭐最关键!!=0 才算通)
#   Stratum:上游层级,16=不可信

# 理想输出第一行的最后应该有一个 *
# MS Name/IP address         Stratum Poll Reach LastRx Last sample
# ===============================================================================
# ^* ntp1.aliyun.com              2   6   377    34  -1423us[-1428us] +/-   33ms

# ===== 验收 2:tracking(本机自己同步到什么水平)=====
chronyc tracking
# 关注字段:
#   Stratum           → 本机层级(上游 S2 + 1 = S3 正常)
#   Leap status       → Normal(00)= 没闰秒安排;Add second / Delete second = 马上闰秒
#   Last offset       → 最近一次调整和 UTC 差多少秒(±0.000xxx 就很好)
#   RMS offset        → 长期均方根误差,理想 < 0.010(局域网<1ms)
#   Root delay / Root dispersion → 越小越好

# ===== 验收 3:sourcestats(每个上游的抖动/偏移统计)=====
chronyc sourcestats -v
# SampleCount > 10 说明已经学习了一会,Freq / Skew 指标稳了

小抄:chronyc sources 里 Reach 第一位变成非零就说明 UDP 123 通了;* 号出现就代表”已经在跟着某源同步”,一般 10~30 秒内出。

3.6 让 chronyd 开机后即使没上游也”看起来已经同步”(系统工具不认 unsync)

很多系统脚本 / systemd-time-wait-sync.service 会等 TimeSync=yes。加:

# RHEL 系
sudo tee -a /etc/sysconfig/chronyd >/dev/null <<'EOF'
OPTIONS="-s"
EOF

# Ubuntu / Debian
sudo tee -a /etc/default/chrony >/dev/null <<'EOF'
OPTIONS="-s"
EOF

-s = 启动时先从 RTC 设一次系统时间(RHEL 默认行为,但 Ubuntu 需要手动加)。


五. 方案 B:ntpd 自建 NTP(老环境兼容)

同样建议能不用就不用,除非维护了 10 年的祖传 restrict notrap noquery 配置不想动。

4.1 安装 + 开机启动

# RHEL 7/8/9
sudo dnf install -y ntp ntpstat
sudo systemctl disable --now chronyd   # chrony 和 ntpd 冲突,关一个
sudo systemctl enable  --now ntpd

# Ubuntu 22.04
sudo apt install -y ntp ntpstat
sudo systemctl disable --now chrony
sudo systemctl enable  --now ntp

4.2 一份可复制的 /etc/ntp.conf(服务端模板)

cat | sudo tee /etc/ntp.conf > /dev/null <<'EOF'
# ========= 1. 上游 =========
server ntp.aliyun.com      iburst
server ntp1.aliyun.com     iburst
server ntp.tencent.com     iburst
server time.cloudflare.com iburst
server ntp.ntsc.ac.cn      iburst

# ========= 2. 孤立模式(上游全挂时当 Stratum 8 对外)=========
server 127.127.1.0
fudge  127.127.1.0 stratum 8

# ========= 3. 漂移 + 统计 =========
driftfile /var/lib/ntp/drift
statsdir /var/log/ntpstats/
statistics loopstats peerstats clockstats
filegen loopstats  file loopstats  type week enable
filegen peerstats  file peerstats  type week enable
filegen clockstats file clockstats type week enable

# ========= 4. restrict 权限:先 deny all,再一条条放(最容易写错的部分)=========
restrict default kod nomodify notrap nopeer noquery    # 外部默认只能给我提供时间、且不能操控我
restrict -6 default kod nomodify notrap nopeer noquery
restrict 127.0.0.1                                     # 本地全部权限(给 ntpq 本机管理用)
restrict ::1
# 内网允许同步(不允许管理)
restrict 10.0.0.0/8        mask 255.0.0.0    nomodify notrap nopeer noquery
restrict 172.16.0.0/12     mask 255.240.0.0  nomodify notrap nopeer noquery
restrict 192.168.0.0/16    mask 255.255.0.0  nomodify notrap nopeer noquery

# ========= 5. 加密 =========
#crypto   # 有对称对称/非对称 Autokey 才开
includefile /etc/ntp/crypto/pw
keys /etc/ntp/keys
trustedkey 1
EOF

restrict 关键字逐个翻译:

关键词效果要不要加给内网客户端
kodKiss-of-Death:客户端太暴力问就发”别问了”包加给 default,对内网别加
nomodify不让对方通过 ntpq/ntpdc 改我配置(安全)所有非本机都要加
notrap不让对方 trap 模式(抓日志流)加
nopeer不接受对方作为 peer(对称对时模式),只接受 server加,防止陌生人跟你对等
noqueryntpq/ntpdc 远程读状态也不允许对内网不要加(否则管理机 ntpq -p 不到)
noserve连时间都不提供,纯我自己当客户端不写

4.3 防火墙 + 验收

防火墙和 chrony 一样(NTP=UDP 123),略。

验收三件套:

sudo systemctl restart ntpd
sleep 10

ntpq -p
# 关键列:
#   remote = 上游;前缀 * 已同步、+ 备选、x 被算法判假时间、. 候选池成员、空格不可达
#   refid = 上游在跟谁同步(.GPS./.PPS./.LOCL. 或 IP)
#   st = stratum;t = type;when = 距上次询问多久秒;poll = 轮询间隔(2^N 秒)
#   reach = 八进制,和 chrony 一样,全 377 最理想
#   delay / offset / jitter = 延迟/偏移/抖动,越小越好

ntpstat   # 这个命令输出一行最直观:synchronized to (IP) at stratum X
watch -n 2 'ntpq -p ; echo ----; ntpstat'

六. 客户端配置(Linux chrony / systemd-timesyncd / Windows / macOS / ntpd)

5.1 Linux 客户端推荐:chrony(和服务端同包,省得装两份)

最精简 /etc/chrony.conf(Ubuntu:/etc/chrony/chrony.conf):

# 内网两台 NTP 主备
server ntp01.mycompany.com iburst
server ntp02.mycompany.com iburst

driftfile /var/lib/chrony/drift
makestep 1.0 3
rtcsync
# 客户端别写 allow,别把自己也变成服务器对外答

开机关机启动:

sudo systemctl enable --now chronyd
sleep 4 ; chronyc tracking

5.2 Linux 客户端轻量选项:systemd-timesyncd(无 chrony 依赖,只有客户端功能)

Ubuntu 20.04+、Debian 11+、RHEL 9 都自带,只做客户端、不能对外当服务器:

# 关掉 chrony / ntpd 其中之一,跟 timesyncd 只留一个
sudo systemctl disable --now chrony ntp   2>/dev/null || true

# 写配置
sudo mkdir -p /etc/systemd/timesyncd.conf.d
cat | sudo tee /etc/systemd/timesyncd.conf.d/10-mycompany.conf > /dev/null <<'EOF'
[Time]
NTP=ntp01.mycompany.com ntp02.mycompany.com
FallbackNTP=ntp.aliyun.com time.cloudflare.com
RootDistanceMaxSec=5
PollIntervalMinSec=32
PollIntervalMaxSec=2048
EOF

sudo systemctl restart systemd-timesyncd
sudo systemctl enable  systemd-timesyncd
sudo timedatectl set-ntp true      # 设为用 NTP 同步(开 timesyncd)
timedatectl timesync-status        # 看同步状态(和 chronyc tracking 同级命令)
timedatectl status                 # 会显示 System clock synchronized: yes + NTP service: active

对比 chrony:systemd-timesyncd 只做 SNTP(简单 NTP,不是完整 NTP 算法),精度一般 100ms 级,办公机/普通业务够;对时钟精度有要求的数据库/etcd 节点还是上 chrony。

5.3 Linux 客户端 ntpd(兼容旧)

cat | sudo tee /etc/ntp.conf > /dev/null <<'EOF'
# 只写内网主备,不需要 restrict allow 啥的(我是客户端)
server ntp01.mycompany.com iburst
server ntp02.mycompany.com iburst
driftfile /var/lib/ntp/drift
restrict default nomodify notrap nopeer noquery
restrict 127.0.0.1
EOF

# RHEL
sudo systemctl enable --now ntpd ; sleep 8 ; ntpq -p
# Ubuntu(服务名为 ntp,不带 d)
sudo systemctl enable --now ntp ; sleep 8 ; ntpq -p

5.4 Windows:域控 / 工作组 / 普通 PC

5.4.1 有 AD 域(99% 公司场景):只在 PDC 模拟器 DC 上手工指上游,域内机器自动跟 DC 同步

在 PDC(五大角色持有者)上管理员 CMD:

:: 指向两台内网 NTP + 一个公网兜底
w32tm /config /manualpeerlist:"ntp01.mycompany.com,0x9 ntp02.mycompany.com,0x9 ntp.aliyun.com,0xa" /syncfromflags:manual /reliable:YES /update
w32tm /config /update
net stop w32time & net start w32time
w32tm /resync /rediscover /nowait
:: 看 Source / Stratum / Last Successful Sync Time
w32tm /query /status
:: 打 5 包看 offset
w32tm /stripchart /computer:ntp01.mycompany.com /dataonly /samples:5

域内其他机器(DC + 客户端 + 服务器)啥都不用改,默认走域层级自动:客户端 → 本地站点 DC → PDC Emulator。

0x9/0xa 这两个 flag 的含义:

  • 0x1 = SpecialPollInterval(按 SpecialPollInterval 定时间隔轮询,默认 3600s)
  • 0x8 = Client mode(NTP 客户端模式)
  • 0x9 = 0x1 | 0x8 = 常用”专用对等体 + 客户端模式”
  • 0xa = 0x2 | 0x8 = UseAsFallbackOnly + Client(兜底)

5.4.2 工作组 / 非域机器 / 个人 Win10/11:

管理员 CMD:

w32tm /config /manualpeerlist:"ntp01.mycompany.com,0x9 ntp.aliyun.com,0x9 time.cloudflare.com,0x9" /syncfromflags:manual /update
w32tm /config /update
net stop w32time & net start w32time
w32tm /resync /force

图形界面(个人 PC):设置 → 时间和语言 → 日期和时间 → 立即同步 → 换服务器地址点”立即同步”。

5.5 macOS / OS X

# 终端命令(需要 sudo)
# 设置 NTP 服务器(systemsetup 一次只设一个,多台用逗号分隔传给 timed)
sudo systemsetup -setnetworktimeserver "ntp01.mycompany.com"
sudo systemsetup -setusingnetworktime on
# 手动触发一次强制同步
sudo sntp -sS ntp01.mycompany.com
# 查看当前配置与同步状态
sudo systemsetup -getnetworktimeserver
sudo systemsetup -getusingnetworktime
# 查看 timed 守护进程日志(排查同步失败)
log show --predicate 'subsystem == "com.apple.time"' --last 1h

图形界面:系统设置 → 通用 → 日期与时间 → 源 → 自定义:写 ntp01.mycompany.com。


七. 常用命令速查(chrony / ntpd / timedatectl / hwclock 四张表)

所有命令”非 root 用户看状态都不写 sudo,只有写/重启/set 才写 sudo”。

6.1 chronyd 客户端/服务端都用 chronyc

#命令作用什么时候用
1chronyc sources -v ⭐列出所有上游 + Reach/Stratum/State第一眼看通不通:有没有 *、Reach != 0、St != 16
2chronyc sourcestats -v ⭐每个源的抖动/样本/频偏统计同步了还不稳时看是哪个源飘
3chronyc tracking ⭐本机自己同步水平:Stratum/Last offset/RMS offset/Leap常用一句话判断:“sync 好了没”
4chronyc activity多少台 peer 在线/离线/可达脚本健康检查一行拿
5chronyc makestep立即硬 step 一次(忽略阈值)手动把大误差(>1s)直接拉回,不用等三次更新
6chronyc burst 4/10 <server>对某源打 4 个 burst 包重启 chronyd 嫌慢手动打
7chronyc offline -a / online -a所有源离线/上线(笔记本合盖前/后)避免 suspend 恢复后一大堆历史超时
8chronyc serverstats服务端统计:收到多少请求/哪些 IP想看”今天多少客户端问了我”
9chronyc clients最近客户端列表 IP/历史请求数排查谁在暴力问(DDoS 前观察)
10chronyc refresh强制重新解析所有 server FQDNDNS 换 IP 了不重启 chronyd 生效
11chronyc reselect / chronyc reselectdist 0立刻重新选 best source某个源挂了不等算法自动
12chronyc waitsync 30 0.01阻塞等 30 秒或同步到 <10ms 才返回CI 里脚本跑前先等同步,不会拿错时间戳

6.2 ntpd 三件套

#命令作用chrony 对应
13ntpq -pn ⭐列源 + reach/offset/jitter,-n 不反解 IPchronyc sources -v
14ntpstat一行输出同步状态`chronyc tracking
15ntpq -c rv看变量:stratum/offset/jitter/rootdispchronyc tracking
16ntpdate -d ntp01.mycompany.com不设时钟、仅调试客户端能不能收到回复chronyc burst + LastRx
17ntpq -p -c as查看 association id + 是否选上chronyc activity
18ntpd -gq一次 step 然后退出(开机前校准常用)chronyc makestep

6.3 时钟/时区/系统硬件互相同步:timedatectl + hwclock

#命令作用备注
19timedatectl status ⭐一屏全览:时区 / NTP 服务是否 active / System clock synchronized / RTC time每次接手一台新机第一条查
20timedatectl list-timezones | grep -i shanghai找时区字符串永远用这个拼 Continent/City,不要手动 ln -sf /usr/share/zoneinfo/… /etc/localtime
21sudo timedatectl set-timezone Asia/Shanghai设置时区完了所有进程读 TZ 会自动更新(Java 进程除外,JDK 读的是启动那一刻缓存的,要重启)
22date / date -Iseconds / date -u看本地时间 / ISO8601 / UTC拿时间戳的最小命令
23sudo timedatectl set-time "2026-08-27 15:03:00"手动设时间(生产禁用,除非断网没同步)NTP 开着时会报 “Automatic time synchronization is enabled” → 先 sudo timedatectl set-ntp false
24sudo timedatectl set-ntp true / false开/关 systemd NTP 服务(timesyncd 或 chrony 接管的那个)
25hwclock -r / hwclock --show读主板 RTCtimedatectl 也会显示 RTC time
26sudo hwclock --systohc ⭐把系统时钟 → 硬件时钟(对好了 NTP 后刷回 RTC,防止关机丢)chrony 的 rtcsync 每 11 分钟自动做这个
27sudo hwclock --hctosys把硬件时钟 → 系统时钟(RTC 比系统准的极罕见情况)systemd 带了 systemd-hwdate.service 开机已经做过
28sudo hwclock --set --date="2026-08-27 15:03:00"改 RTC除了 BIOS 没电导致 RTC 回到 1970/2000,否则别碰
29timedatectl show机读格式拿状态脚本里用

6.4 Windows w32tm 常用

#命令作用
30w32tm /query /status本机同步状态
31w32tm /query /peers我正在跟哪些 peer 同步
32w32tm /query /configuration所有 w32time 注册表配置大 dump(排查组策略)
33w32tm /resync /rediscover /force立即重同步,忽略冷却时间
34w32tm /stripchart /computer:ntp01 /dataonly /samples:5连打 5 包看 offset
35w32tm /config /update应用了新配置后刷新
36net stop w32time & w32tm /unregister & w32tm /register & net start w32timew32time 炸了/报错 1290 直接重置服务(最狠招)

八. 8 个最高频的坑(按出现率排序)

🐞 1. chronyc sources 里 Reach = 0 / Stratum 全 16 / ^? xxx ...

99% = 网络没通。 一步步查:

# ① DNS 能解析吗?
getent hosts ntp01.mycompany.com
# ② UDP 123 能出去吗?(NTP 是 UDP,不能 nc -zv,用 chronyd/ntpdate 调试更准)
sudo chronyd -Q -q 'server ntp01.mycompany.com iburst'      # 调试模式跑一次,退出码 0=拿到了样本
# ③ 服务端防火墙漏开 UDP 123?上服务端:
sudo ss -ulpn | grep :123
# ④ 服务端写 allow 了吗?(chrony.conf)没有 allow 客户端永远 Reach=0
# ⑤ AWS/阿里云安全组、OSI 4-7 层 ACL、公司出口防火墙是不是挡了 UDP 123?

🐞 2. chronyc tracking 里 System time 永远不 “synchronized: yes”

  • 等够时间:冷启动一般 10~30 秒。用 chronyc waitsync 30 0.01 阻塞等一下
  • 上游只有一个/全挂了:chrony 找不到”可信的共识”会一直等。再加 1~2 个上游
  • 本机时间差太大 + makestep 没开:date 先看一下,误差>几小时的话开 makestep 1.0 3 然后重启 chronyd

🐞 3. 虚拟机 / VMware / KVM / 笔记本合盖后唤醒,时间差几分钟到几小时

  • chrony 首选:makestep 1.0 3 + rtcsync。休眠唤醒后 chrony 30 秒内自动收敛
  • 同时关 VMware Tools / open-vm-tools 的 “跟宿主机同步时间”:否则宿主机不准会把你硬拽回(Tools 的同步跟 chrony 打架,时间来回跳)
    # VMware: 把 tools.syncTime = "FALSE" 放进 .vmx;或者在虚拟机里:
    vmware-toolbox-cmd timesync disable
    # open-vm-tools: 编辑 /etc/vmware-tools/tools.conf 设 time.synchronize.tools.enable=false
    sudo sed -i 's/^time.synchronize.tools.enable.*/time.synchronize.tools.enable=false/' /etc/vmware-tools/tools.conf 2>/dev/null || true
    sudo systemctl restart open-vm-tools 2>/dev/null || true
  • Hyper-V / KVM:看 virt-manager → VM → 显示 → “Clock” 里不要勾选 “Sync host time with guest”

🐞 4. 时区 UTC / 本地时区 / 时间差 8 小时

根因:把系统时钟设成本地时间了(Windows 默认;Linux 默认 UTC)。永远用 UTC 当系统时钟,时区偏移交给 /etc/timezone。

# 正确姿势:
sudo timedatectl set-timezone Asia/Shanghai
timedatectl   # 看 TZ/System clock synchronized/在 UTC 那一栏一致就对了
# 错误姿势(不要做):
# sudo ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime   这会导致 RTC=local time

有一台 Windows + Linux 双系统机器时间差 8 小时的经典坑:Windows 默认 RTC=本地时间,Linux 默认 RTC=UTC。统一方式(推荐改 Windows 让 RTC=UTC,不要反过来改 Linux):

Windows 管理员 CMD → reg add "HKLM\System\CurrentControlSet\Control\TimeZoneInformation" /v RealTimeIsUniversal /t REG_DWORD /d 1 /f
然后把 Windows NTP 重新同步一次。

🐞 5. ntpq -p 一直显示 .INIT. / reach=0

同 chrony 的坑 1,另外还有一个 ntpd 独有的:

restrict default ... noquery noserve

如果你把 noserve 写到 restrict 里了,上游会连时间都不回给你。检查 restrict 行不要乱加 noserve。

🐞 6. 时间对但日志/程序看的还是旧时间

  • Java / Go / 部分 daemon 进程启动时会缓存时区+闰秒偏移。改了 timedatectl set-timezone 后一定要重启这些进程。最常见的是 Java 应用。
  • 验证:sudo cat /proc/<PID>/environ | tr '\0' '\n' | grep TZ,如果进程自己显式设了 TZ,系统设置无效。

🐞 7. Kerberos 报错 “Clock skew too great” / kinit 失败

  • KDC 与两端机器时间差超 5 分钟
  • 全量排查:for h in kdc01 kdc02 app01 app02; do ssh $h timedatectl status | head -4; done,看 Time zone、System clock、NTP service 三样是不是一致
  • 紧急临时修:KDC + 客户端都 chronyc makestep 立刻对齐,然后再找根因(比如有台机器 chronyd 根本没开)

🐞 8. RTC / 主板电池没电(BIOS 时间回到 2000-01-01 或 1970)

# 症状:关机后再开机时间全错;chrony 即使同步了关机一丢
sudo hwclock -r   # RTC 直接读错成 1970/2000
  • 短期:timedatectl set-timezone + 开 rtcsync/每次 hwclock --systohc 顶一顶
  • 根治:换主板 CR2032 电池(台式机 3 元钱,服务器要联系供应商)

附录:NTP 新部署自检清单(6 条勾完再上线)

  • 服务端:chronyc sources → 有一个 *,Reach 列至少有非零值,Stratum <= 10
  • 服务端:chronyc tracking → Leap status = Normal,RMS offset < 100ms
  • 服务端:内网任意一台新机 chronyc -h ntp01.mycompany.com sources 能拿到响应(或直接 chronyd -Q -q 'server ntp01 iburst')
  • 客户端:timedatectl → NTP service: active,System clock synchronized: yes,TZ 统一 Asia/Shanghai(或你所在时区)
  • 跨平台:Windows w32tm /query /status 的 Source 指向你 PDC/内网 NTP,Stratum 不是 0 或 16
  • 监控接入:Prometheus + node_exporter 暴露 node_ntp_offset_seconds / chrony_exporter 暴露 chrony_tracking_last_offset_seconds,设告警 > 500ms warning、> 5s critical

延伸:如果你机房有 GPS/北斗 PPS 卡想搭真 Stratum 1,或想上 PTP/IEEE 1588(给金融交易/5G/TSN 亚微秒级同步),可以按 chrony 的 hwtimestamp + pps 文档或 Linux PTP ptp4l / phc2sys 体系再做一层;大多数场景到 NTP + chrony 内网两台主备已经够用。

问问 AI