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

オープン
#14,265 コメント 2 件 リアクション 0 件 担当者 1 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

@wanghe-fit2cloud がすでに取り組んでいます。

2026年11月2日 から。

評価

難易度
3/5
見積もり時間
1〜2日
初心者へのやさしさ
50/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
go, linux

調査の方向性

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.

索引モデルが issue の本文から書いたものです。

説明

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 二进制打补丁。

主要言語
Go
スター
37.3k
フォーク
3.4k
平均マージ
8時間 21分
マージ済み PR(30日)
124

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

1Panel-dev/1Panel のほかの issue

1Panel-dev/1Panel の issue をすべて見る

似ている issue

Go の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。