给定时任务加一层保险:让 cron 失败不再静默
定时任务最让人头疼的不是它报错,而是它悄悄不跑了。备份没生成、报表没发出、清理脚本没执行,直到有人问起才发现,中间已经丢了好几天的数据。cron 本身很安静,失败也不会主动敲门,所以我们要给它加一层保险,让失败变得可见、可查、可恢复。
为什么失败容易静默
第一,cron 的输出默认发邮件,而很多服务器根本没有配置本地邮件,输出就此消失。第二,脚本中途出错不一定影响退出码,比如管道前半段失败、后半段却成功,整体仍被判定为成功。第三,任务依赖外部条件,数据库连接失败、磁盘写满、第三方接口超时,都会让任务空转一轮,却不留任何痕迹。把这三类问题分开处理,保险就有了落点。
第一层:输出一定要落盘
不要让脚本裸跑。把标准输出和标准错误都重定向到带日期的日志文件,并定期轮转,避免单个日志把磁盘撑满。例如:
0 2 * * * /opt/backup/backup.sh >> /var/log/backup-$(date +\%Y\%m\%d).log 2>&1
注意 cron 里百分号需要转义,这个小细节经常导致任务本身无法解析。日志落盘后,排查就不再靠猜测,而是先看最后一行写了什么、在哪一步停下。
第二层:用退出码触发提醒
脚本结尾要明确返回退出码,关键步骤失败就立刻退出,不要继续假装完成。可以在脚本开头加上 set -euo pipefail,让未定义变量和管道失败也能被捕获。更进一步,用一个包装脚本判断退出码,非零就发通知:
#!/bin/bash
/opt/backup/backup.sh
if [ $? -ne 0 ]; then
echo "备份任务失败,请检查日志" | mail -s "备份失败" ops@example.com
exit 1
fi
通知渠道不一定要复杂,邮件、企业微信机器人、短信都可以,关键是有人会看到。没有人看的告警,等于没有告警。
第三层:防止重复与漏跑
定时任务还怕两种极端:重叠执行和长期漏跑。耗时任务可以用 flock 加锁,保证同一时间只有一个实例在跑;幂等设计则保证重跑不会重复写入或重复扣费。至于漏跑,可以在任务末尾写一个心跳文件,记录最后成功时间,再由另一个检查脚本定期比对,超过阈值就告警。这样即使 cron 服务本身停了,也能被发现。
上线前自查清单
写完定时任务后,不妨对照这四条检查一遍:输出是否落盘且能轮转;失败时退出码是否为非零;失败后是否有人收到通知;重跑是否安全、漏跑是否可发现。把这四条写进任务说明里,接手的人也不用重新踩坑。
定时任务的价值不在写得多巧妙,而在跑得可靠。给它留日志、留退出码、留心跳,失败就不再是悄悄发生的坏消息,而是一条可以马上处理的提醒。这层保险花不了多少时间,却能在关键时刻省下很多排查成本。
- 点赞
- 收藏
- 关注作者
评论(0)