搜索全站
安装部署 13 分钟阅读

WordPress 服务器时间不同步的排查与 NTP 修复

定时发布文章没发出来、日志时间差 8 小时、SSL 证书校验失败——都可能是服务器时间不对。本文讲清 WordPress 三层时间来源,给出 Linux 时区与 NTP 配置方法和逐项排查步骤。

U
UFO_PF 2023-03-27 · 阅读 13 分钟
Wo 安装部署
阅读提示
本文约 5,177 字,预计阅读 13 分钟。文中命令与配置均经过实测,可直接参考执行。

引言:时间不对会引发一堆怪事

服务器时间不准导致的症状千奇百怪,而且很难联想到是时间问题:

  • 设置了”明天 9 点发布”的文章,一直显示”错过计划”(Missed schedule);
  • 评论时间显示 8 小时前,其实是刚刚发的;
  • 后台「工具 – 站点健康」提示”计划任务未运行”;
  • 备份文件名日期错乱,自动清理脚本删错了文件;
  • SSL 证书明明没过期却报”证书尚未生效”或”已过期”;
  • 阿里云、腾讯云、AWS 的 API 报 SignatureDoesNotMatch;
  • CDN 缓存刷新接口返回时间戳错误。

后两条尤其关键:云厂商的 API 签名普遍带时间戳,服务器时间偏差超过 15 分钟,所有签名请求都会失败。

原理分析:WordPress 时间的三层来源

第一层:Linux 系统时间

date
# Mon Mar 10 14:30:00 CST 2025

这是最底层,PHP 的 time()、date() 都取自这里。Linux 有两个时钟:

  • 系统时钟(System Clock):内核维护的软件时间,开机时从硬件时钟读取;
  • 硬件时钟(RTC):主板电池供电的时钟,关机也走,但精度差(一天可能差几秒)。

两者都可能不准。

第二层:PHP 时区

; php.ini
date.timezone = Asia/Shanghai

关键区别:time() 返回的是 UTC 时间戳(与时区无关,全球一致),但 date() 格式化时才应用时区。所以时区设错的表现是”显示差 8 小时”,而不是”时间戳错了”。

第三层:WordPress 时区

后台「设置 – 常规 – 时区」,可选 UTC+8、Asia/Shanghai 等。WordPress 内部一律以 UTC 存储时间戳,显示时按设置转换——所以改时区不会破坏已有数据。

三层的正确关系:

层 影响范围 正确值
系统时间 所有程序、日志、证书校验、API 签名 准确(时区配置正确)
PHP 时区 date() 输出、插件日志 Asia/Shanghai
WordPress 时区 前台显示、定时发布计算 Asia/Shanghai 或 UTC+8

系统时间是根,它错了其他两层怎么设都没用。

保姆级实操

第一步:检查当前状态

date
sudo hwclock --show
timedatectl

典型输出:

               Local time: Mon 2025-03-10 14:30:00 CST
           Universal time: Mon 2025-03-10 06:30:00 UTC
                 RTC time: Mon 2025-03-10 06:30:00
                Time zone: Asia/Shanghai (CST, +0800)
System clock synchronized: yes        ← 关键
              NTP service: active     ← 关键
          RTC in local TZ: no

如果 System clock synchronized: no 或 NTP service: inactive,就是没同步。

timedatectl timesync-status       # systemd-timesyncd
chronyc tracking                  # chrony
ntpstat                           # 老 ntpd

第二步:设置时区

timedatectl list-timezones | grep -i shanghai
sudo timedatectl set-timezone Asia/Shanghai
date

无 systemd 的老系统:

sudo cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
echo "Asia/Shanghai" | sudo tee /etc/timezone

第三步:配置 NTP 自动同步

方案 A:systemd-timesyncd(Ubuntu 默认,轻量)

sudo timedatectl set-ntp true
sudo systemctl enable --now systemd-timesyncd

编辑 /etc/systemd/timesyncd.conf:

[Time]
NTP=ntp.aliyun.com time.cloudflare.com pool.ntp.org
FallbackNTP=ntp1.aliyun.com ntp2.aliyun.com
sudo systemctl restart systemd-timesyncd
timedatectl timesync-status

方案 B:chrony(推荐,精度更高,CentOS 默认)

sudo apt install chrony -y        # Debian/Ubuntu
sudo dnf install chrony -y        # CentOS/Rocky
sudo systemctl enable --now chronyd

编辑 /etc/chrony/chrony.conf:

server ntp.aliyun.com iburst
server ntp1.aliyun.com iburst
server time.cloudflare.com iburst
server ntp.tencent.com iburst
pool pool.ntp.org iburst

# 允许查询的客户端(仅内网服务器需要)
# allow 192.168.0.0/16

# 记录时钟漂移
driftfile /var/lib/chrony/drift

# 启动时如果偏差大于 1 秒,立即步进校正(前 3 次)
makestep 1.0 3

rtcsync
sudo systemctl restart chronyd
chronyc sources -v        # 看时间源状态
chronyc tracking          # 看偏差

chronyc sources 输出里,行首是 ^* 表示当前正在使用的时间源。

第四步:手动强制同步(偏差大时)

# chrony
sudo chronyc -a makestep

# systemd-timesyncd
sudo systemctl stop systemd-timesyncd
sudo timedatectl set-ntp false
sudo timedatectl set-ntp true

# 老式 ntpdate(需安装)
sudo ntpdate -u ntp.aliyun.com

偏差超过 1000 秒时 NTP 默认不会平滑校正,需要 makestep 强制跳变。

第五步:同步硬件时钟

sudo hwclock --systohc     # 系统时间写入硬件时钟
sudo hwclock --show

第六步:配置 PHP 时区

php -i | grep "date.timezone"

如果没有值,编辑 php.ini:

date.timezone = Asia/Shanghai

宝塔面板:软件商店 → PHP 设置 → 配置文件,搜索 date.timezone 修改。

sudo systemctl restart php8.2-fpm
php -r 'echo date("Y-m-d H:i:s T");'

第七步:核对 WordPress 时区

wp option get timezone_string --allow-root
wp option get gmt_offset --allow-root

或后台「设置 – 常规」。推荐用城市名(Asia/Shanghai)而不是 UTC+8,因为城市会自动处理夏令时(虽然中国没有夏令时,但规范上更好)。

命令行设置:

wp option update timezone_string 'Asia/Shanghai' --allow-root

第八步:验证定时发布

# 查看当前的计划任务
wp cron event list --allow-root

# 手动触发一次(看是否正常执行)
wp cron event run --due-now --allow-root

# 查看 WordPress 认为的当前时间
wp eval 'echo current_time("mysql"), " | UTC: ", gmdate("Y-m-d H:i:s");' --allow-root

两个时间应该相差正好 8 小时。如果不是,说明时区配置有问题。

常见踩坑

  1. Docker 容器时间不同步:容器默认共享宿主机内核时钟,不能在容器里改时间。时区可以通过挂载解决:

yaml
volumes:
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
environment:
TZ: Asia/Shanghai

时间同步必须在宿主机上做。

  1. PHP-FPM 缓存了时区:改了 php.ini 没重启 FPM,还是旧的。必须 restart php-fpm,不是 reload。
  2. 案例:某站定时发布一直失败,显示”错过计划”。排查发现服务器时区是 UTC,WordPress 时区设的是 UTC+8,wp_next_scheduled 计算出的时间戳和实际差 8 小时,cron 判断”还没到”。把系统时区和 PHP 时区统一改成 Asia/Shanghai 后解决。三层必须一致。
  3. 虚拟机时间漂移:VMware/KVM 虚拟机的时钟容易漂移(尤其 CPU 负载高时)。VMware 装 open-vm-tools,KVM 用 chrony + ptp 或启用 kvm-clock。虚拟机更应该开 NTP。
  4. NTP 端口被封:NTP 用 UDP 123。有些云安全组/机房防火墙封了这个端口,导致同步失败。用 chronyc sources 看状态是 ? 或 x 说明不可达。改用 HTTP 时间服务或联系机房。
  5. “Missed schedule” 的其他原因:即使时间对了,wp-cron 是伪定时任务(靠访问触发),低流量站点也会”错过计划”。真正的解法是关掉 WP-Cron 改用系统 cron:

php
// wp-config.php
define( 'DISABLE_WP_CRON', true );

bash
# 系统 crontab,每 5 分钟触发
*/5 * * * * cd /var/www/mimangfei && wp cron event run --due-now --allow-root > /dev/null 2>&1

  1. 改时区后历史数据显示错乱:不用担心,数据库存的是 UTC,改时区只影响显示。

总结

时间问题排查顺序:timedatectl 看是否同步 → date 看时区 → php -i 看 PHP 时区 → WordPress 后台看站点时区 → wp eval 对比 current_time 和 gmdate 是否差 8 小时。修好后开 NTP(chrony 优先),把 hwclock --systohc 写入硬件时钟,并把 NTP 状态纳入监控。顺带一提,如果你发现”定时发布不准”,除了时间问题还要确认 WP-Cron 是否正常工作——低流量站建议按上面第 6 条改成系统 cron 驱动。日常巡检可以把时间检查加进WordPress 月度安全巡检清单,而站点健康里的”计划任务”提示正是这个问题的常见表现(另见WordPress 站点健康故障排除模式)。

U
UFO_PF作者

专注 WordPress 生态的实战作者,内容以「可复制、可验证」为第一原则。

留下你的想法

邮箱地址不会被公开。带 * 的为必填项。