[Bug] NTP time synchronization ignores UTC offset and causes a one-hour rollback during DST fallback

Đang mở
#14,265 2 bình luận 0 reaction 1 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

@wanghe-fit2cloud đang làm issue này rồi.

Từ ngày 2/11/2026.

Đánh giá

Độ khó
3/5
Thời gian dự kiến
1-2 ngày
Mức phù hợp với người mới
50/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
go, linux
Lĩnh vực
infrastructure

Hướng nghiên cứu

Start with handleNtpSync in agent/app/service/cronjob_helper.go, then UpdateSystemTime in agent/utils/ntp/ntp.go, and the DateTimeLayout constant in agent/constant/common.go. The issue's read-only TZ=America/Los_Angeles date --date=... commands show the ambiguity without changing the clock. Done means the sync path passes an unambiguous instant (for example a Unix timestamp or a string with an explicit offset) so the 01:30 PST case resolves to 09:30 UTC, and the maintainers accept the compatibility approach.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

type: to-be-verified
Contact Information

请通过本 Issue 联系。

1Panel Version

v2.4.1(实际发生故障的版本)。

另外静态核对了 v2.4.2 的相关源码,仍使用相同的无时区字符串校时方式;尚未在 v2.4.2 上运行完整场景。

Problem Description

在使用 America/Los_Angeles 时区的 Linux 服务器上,1Panel 内置的“同步服务器时间”计划任务在 2026-11-01 夏令时结束当天,将系统 UTC 时间实际向后调整了约 3600 秒。

配置如下:

  • 计划任务类型:内置 NTP 同步(type=ntp),不是自定义脚本。
  • Cron 表达式:30 1 * * *,每天当地时间 01:30。
  • NTP server:pool.ntp.org。
  • 操作系统实际时区:America/Los_Angeles。

当天出现两次当地时间 01:30:

当地时间 UTC 北京时间
2026-11-01 01:30 PDT(UTC-07:00) 08:30 UTC 16:30
2026-11-01 01:30 PST(UTC-08:00) 09:30 UTC 17:30

任务在这两个时间分别执行了一次,面板中均显示成功。第二次执行时,1panel-agent.service 调用了不带时区/偏移的命令:

date -s '2026-11-01 01:30:00'

服务器上的 date 将这个有歧义的字符串解释成第一次 01:30(PDT),导致 UTC 从约 09:30 回到 08:30。这不是仅仅切换时区显示,系统时钟确实发生了回拨。

实际影响:依赖时间戳新鲜度检查的业务将已有的健康检测/额度记录判定为未来数据,从而拒绝请求;日志时间也回到了前一小时。系统日志中 chrony 随后记录了 Backward time jump detected!,并发现系统时间偏差约 3600 秒。

Steps to Reproduce
1. 无副作用的核心复现(不修改系统时间)

在安装了相应时区数据的 Linux / GNU date 环境执行:

TZ=America/Los_Angeles date --date='2026-11-01 01:30:00' '+%s'
# 实际输出:1793521800,即 2026-11-01 08:30:00 UTC

TZ=America/Los_Angeles date --date='2026-11-01 01:30:00 -0800' '+%s'
# 实际输出:1793525400,即 2026-11-01 09:30:00 UTC

两个结果相差 3600 秒。第二个时间才是当天第二次 01:30 对应的时刻;如果在格式化过程中丢掉 -0800,就变成第一个结果。

2. 完整场景
  1. 在隔离测试虚拟机安装 1Panel v2.4.1,操作系统使用 America/Los_Angeles 时区。
  2. 创建内置“同步服务器时间”任务,NTP 为 pool.ntp.org,Cron 为 30 1 * * *。
  3. 在夏令时结束当天第二次 01:30(本次为 2026-11-01 09:30 UTC)执行该任务,或在该重叠时间窗口内手动执行内置同步任务。
  4. 检查系统 UTC、journal 的时间跳变记录和实际执行的 date -s 命令。
  5. 本次实际发生的结果:系统 UTC 回拨约一小时,任务仍显示成功。

不建议为复现在生产服务器上手动调整时钟;上面的只读命令已能展示歧义解析问题。

The expected correct result

NTP 校时应保留唯一的绝对时刻,正确区分重复出现的本地时间,不能因为夏令时重叠而把系统 UTC 向后拨一小时。

正常的夏令时切换只应改变本地时间显示的偏移,不应导致系统 UTC 发生这种跳变。

Related log output

以下为现场记录,已省略主机名、IP、业务标识等信息。journal 时间使用原始 __REALTIME_TIMESTAMP 转成 UTC,避免当地时间重叠造成歧义:

2026-11-01T09:30:00.060274+00:00
  _SYSTEMD_UNIT=1panel-agent.service
  _COMM=sudo
  COMMAND=/usr/bin/date -s 2026-11-01 01:30:00
  __MONOTONIC_TIMESTAMP=593218107748

2026-11-01T08:30:00.000184+00:00
  _SYSTEMD_UNIT=systemd-resolved.service
  Clock change detected. Flushing caches.
  __MONOTONIC_TIMESTAMP=593218112084

2026-11-01T08:30:00.014479+00:00
  _SYSTEMD_UNIT=systemd-journald.service
  Time jumped backwards, rotating.
  __MONOTONIC_TIMESTAMP=593218126380

2026-11-01T08:31:00.635912+00:00
  _SYSTEMD_UNIT=chrony.service
  Backward time jump detected!

chronyd subsequent log:
  System clock wrong by 3600.048672 seconds

单调时间持续向前,实际 UTC 时间却在 date -s 后倒退,能确认事件顺序。

1Panel 任务数据库中,第二次执行的同一任务记录甚至出现结束时间早于开始时间的情况:

created_at = 2026-11-01 01:30:00.009521025-08:00
end_at     = 2026-11-01 01:30:00.001613316-07:00
status     = Success

对应任务日志:

2026/11/01 01:30:00 执行 [cronjob-同步服务器时间] 任务开始 [START]
2026/11/01 01:30:00 ntp server: pool.ntp.org
2026/11/01 01:30:00 系统时间同步 成功
2026/11/01 01:30:00 [TASK-END]
Additional Information
源码定位

以 v2.4.1 的固定 tag 为例:

  1. handleNtpSync 将 NTP 返回值按 constant.DateTimeLayout 格式化后传给 UpdateSystemTime。
  2. DateTimeLayout 为 2006-01-02 15:04:05,不包含 UTC 偏移。
  3. UpdateSystemTime 执行 date -s <dateTime>,让操作系统重新解析这个有歧义的本地时间。

v2.4.2 的对应调用与格式化定义也保留了这一行为:

修复方向建议

校时链路应直接传递 Unix 时间戳(例如使用 GNU date 支持的 @<Unix timestamp>),或传递包含明确 UTC 偏移的格式,避免把绝对时间转成无偏移的本地时间后再解析。具体实现和兼容性由项目维护者决定。

目前现场已通过现有 chrony 校准时间并刷新业务状态恢复服务;未对 1Panel 二进制打补丁。

Ngôn ngữ chính
Go
Star
37.3k
Fork
3.4k
Merge trung bình
8 giờ 21 phút
Pull request đã merge (30 ngày)
124

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của 1Panel-dev/1Panel

Tất cả issue của 1Panel-dev/1Panel

Issue tương tự

Thêm issue về Go

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.