根本原因是系统时区未设为Asia/Shanghai且NTP未真正同步:timedatectl显示时区非CST、System clock synchronized为no,或chronyc tracking显示Offset超±100ms,均会导致cron按UTC执行或漏跑。

宝塔面板计划任务执行时间不准,根本原因不是面板本身出错,而是系统时间或时区没设对——cron 完全依赖系统 date 输出,它不读 PHP 或 MySQL 的时区配置,只认 timedatectl 看到的那个时间。
计划任务总在 UTC 时间执行,实际想按北京时间跑
这是最常见现象:你设了“每天 2:00 执行备份”,结果日志里显示是凌晨 2:00(UTC),也就是北京时间上午 10:00。问题出在系统时区仍是 Etc/UTC 或 US/Eastern,而 cron 默认按系统本地时区解析时间表达式。
- 执行
timedatectl查看当前时区,若不是Asia/Shanghai,立刻运行:sudo timedatectl set-timezone Asia/Shanghai - 改完后别急着加任务,先执行
date确认输出带CST或+0800,否则cron仍按旧时区算 - 宝塔的「计划任务」界面里填的时间,就是按这个系统时区理解的,不存在“面板自动转时区”这回事
计划任务漏跑、延迟执行,NTP 没真正同步
哪怕你点过面板里的【同步】按钮,也只是临时调用一次 ntpdate,之后系统时间会持续漂移。虚拟机尤其明显,一两天就偏个几十秒,导致 cron 判定“该执行的时间已过去”,直接跳过。
- 运行
timedatectl status,重点看两行:NTP enabled: yes和System clock synchronized: yes—— 缺一不可 - 如果
System clock synchronized: no,说明chronyd或systemd-timesyncd根本没连上 NTP 服务器,得查防火墙是否放行 UDP 123 端口,或换阿里云源:ntp1.aliyun.com - 验证真实偏差:运行
chronyc tracking | grep "Offset",值超过 ±100ms 就算异常,cron可能已开始误判
宝塔计划任务里写 date 命令,输出却是 UTC 时间
这不是 bug,是预期行为。你在计划任务脚本里写的 date,走的是系统默认 locale 和时区,和 PHP 的 date.timezone 无关。如果你在脚本里需要明确北京时间,不能靠“系统自动对齐”。
- 脚本开头加一行:
export TZ=Asia/Shanghai,再执行date就可靠 - 或者直接用:
date -d "TZ=\"Asia/Shanghai\" now",绕过环境变量依赖 - 别在脚本里写
timedatectl set-timezone—— 计划任务默认以root运行,但反复切时区可能干扰其他服务
真正容易被忽略的点:宝塔计划任务页面右上角显示的时间,是前端 JS 缓存的,可能和 date 命令输出不一致;排查时必须以 SSH 里敲 date -R 为准,而不是信面板 UI。


















