问题出现得很突然,日志倒是留得挺全。阿里云 2 核 4G 的 Ubuntu 22.04,timedatectl 显示 Asia/Shanghai,crontab 顶部写了 CRON_TZ=Asia/Shanghai,任务还是在北京时间早上 8 点跑而不是配置的 0 点,日志时间戳也全是 UTC。

刚开始盯着「容器里的 cron 没有挂 /etc/localtime 和 tzdata」,折腾了半个多小时,排掉了。

原因不止一个,得分开看。系统 cron 版本不支持 CRON_TZ,写了也被忽略。还有一种是CRON_TZ 只影响调度,不影响脚本内部取到的时间。

不容易想到的是,任务被 systemd timer 接管,时区由 timer 决定。

第一件事是确认 cron 实现和版本

cron --version 2>/dev/null; dpkg -l | grep cron

然后检查系统时区和 cron 环境

timedatectl && cat /etc/timezone

接着在脚本里显式导出 TZ

printf 'export TZ=Asia/Shanghai\n' | cat - /opt/scripts/job.sh > /tmp/job.sh && mv /tmp/job.sh /opt/scripts/job.sh

末了按实际生效时间重排任务

crontab -l | grep -v CRON_TZ | sed 's/^0 0/0 8/' | crontab -

这类改动我都写进变更记录,过两周再出问题时能对上号。

别只看报错消失,验证要多做一步。任务在北京时间 0 点触发,脚本内 date 输出 +0800,日志时间戳与预期一致。

提醒一点。调度时区和业务时区是两件事,脚本里取时间要显式设 TZ,否则换台机器结果又不一样。拖得越久,排查成本越高,因为现场状态会被后续操作覆盖。

作者 9823189