chronyd 服务启动失败 “Could not step system clock” 的权限与 adjtime

7次阅读

“Could not step system clock”是chronyd因缺少CAP_SYS_TIME能力而无法直接跳变系统时间导致的启动失败错误;根本原因是非特权用户进程被内核禁止调用clock_settime(),需通过setcap添加能力并配置systemd service的CapabilityBoundingSet和AmbientCapabilities来修复。

chronyd 服务启动失败 “Could not step system clock” 的权限与 adjtime为什么 adjtime(2) 成功但 clock_settime(2) 失败

adjtime() 是渐进式调速(slew),仅调整时钟频率,不改变当前时间戳,普通用户可调;clock_settime(CLOCK_REALTIME, ...) 是直接写入新时间,属于高危操作,受 Linux capability 限制。chronyd 启动时若检测到系统时间偏差过大(默认 > 0.128 秒),会优先尝试 step(更快收敛),失败后才 fallback 到 slew —— 但若 step 失败且未配置允许降级,就直接报错退出。

  • chronyd -d -x 可强制只用 slew 模式(绕过 step),适合调试
  • 实际生产中不建议长期用 -x,它无法修正大偏差,可能让 NTP 同步失效
  • 检查偏差大小:chronyc tracking 中的 System time offset

修复 “Could not step system clock” 的三种可行方式

核心是让 chronyd 进程获得 CAP_SYS_TIME,而非改用 root 运行(不安全):

  • 给 chronyd 二进制文件添加 capability:sudo setcap cap_sys_time+ep /usr/bin/chronyd
  • 确认生效:getcap /usr/bin/chronyd 应输出 /usr/bin/chronyd = cap_sys_time+ep
  • 若使用 systemd,需在 service 文件中显式声明能力(否则 setcap 可能被忽略):
    CapabilityBoundingSet=CAP_SYS_TIMEAmbientCapabilities=CAP_SYS_TIME
  • 重启服务:sudo systemctl restart chronyd,再查 journalctl -u chronyd -n 20

/etc/chrony.conf 中的 makestep 配置影响 step 行为

makestep 指令控制 chronyd 是否以及何时执行 step,它不解决权限问题,但决定是否触发该错误:

  • makestep 1.0 -1:偏差 ≥1 秒时无条件 step(最可能触发错误)
  • makestep 0.128 3:仅在启动后前 3 秒内、偏差 ≥128ms 时 step(更保守)
  • makestep 0 0:完全禁用 step(等同于 -x,不推荐)
  • 注意:即使配置了 makestep,若 capability 缺失,仍会报错退出,不会静默 fallback

真正容易被忽略的是 capability 和 systemd service 配置的配合 —— 单独 setcap 在某些发行版(如 RHEL 8+/centos stream)的 systemd 环境下并不生效,必须补全 CapabilityBoundingSetAmbientCapabilities 才能落地。

text=ZqhQzanResources