在印度机房跑备份脚本,夏令时把 cron 挪了一小时
去年在一台印度本地的备份机上排一个很怪的问题。环境是 Ubuntu 20.04,cron 里挂了一条每天 02:00 跑的全量备份,数据量不大,PG 大概 40GB,打出来的 dump 大约 9GB,直接 gzip 后 rsync 到另一台机器。现象是:三月的某个周一,备份文件的时间戳变成 03:00 之后,第二天又变成 01:00 之后,隔一天才稳回 02:00。没有报错,备份也完整,就是时间对不上,下游按文件名日期归档的脚本因此多算了一天。
我先确认了机器本身的时区:
timedatectl
# Time zone: Asia/Kolkata (IST, +0530)
# RTC in local TZ: no
印度没有夏令时,这点没问题。问题出在这台机器装系统时选的是 Asia/Kolkata,但 cron 的调度不是只看系统时区。我查了 journalctl -u cron 里那几天的记录,发现触发时间确实整体偏移,于是去看了 /etc/localtime 和 cron 进程的启动环境:
ls -l /etc/localtime
# -> /usr/share/zoneinfo/Asia/Kolkata
cat /etc/timezone
# Asia/Kolkata
systemctl show cron -p Environment
结果是 cron 服务启动时继承了一个 TZ=Asia/Kolkata 的 Environment,但系统里另一个被调用的脚本自己 export TZ=UTC,两者在夏令时切换日附近对不上。真正的修复不是改 cron,而是把备份脚本里所有和日期相关的逻辑统一到一个时区:
#!/bin/bash
export TZ=Asia/Kolkata
STAMP=$(date +%Y%m%d)
pg_dump -Fc appdb > /backup/appdb-${STAMP}.dump
同时在 crontab 里显式写 CRON_TZ=Asia/Kolkata,不要依赖继承。
这样做的好处是调度和命名用的是同一个时区,代价是所有下游消费方都得知道文件名里的日期是 IST,不是 UTC。我们后来在下游归档脚本里加了一个显式的时区参数,不再用文件名直接拼 UTC 时间。
这套做法在两种情况下会失效:一是机器上装了多个 cron 实现(比如 cronie 和 systemd timer 混用),CRON_TZ 不一定被认;二是备份本身跨了午夜,文件名里的日期只能代表开始时间,不能代表数据截止时间。我自己踩过的坑是只改了脚本没改 crontab,结果文件名对了、触发时间还是漂的,排查时白看了一轮日志。
你们在印度机房跑定时任务时,是统一用 IST 命名,还是全部转成 UTC 再落盘?下游对文件名日期的解读有没有出过类似的对不上的情况?
0 条评论
还没有评论,写下第一条。