如何监控定时任务(Cron Job)是否正确执行?
定时任务监控(心跳监控)原理:任务成功后向监控端点发一次请求,没收到就告警。备份漏跑、报表失败第一时间知道,附脚本改造示例与实现方案。
数据库备份、对账任务、邮件群发——这些定时任务(cron job)的可怕之处在于它们失败时通常悄无声息。没有用户投诉,没有错误页面,只是在三个月后需要恢复备份时,发现备份从三个月前就没再成功过。定时任务监控(也叫心跳监控)解决的就是这个盲区。
心跳监控的原理
思路反直觉但极有效:不去监控"任务失败了",而是监控"任务成功过"。
- 为每个定时任务创建一个心跳监控端点(一个唯一 URL);
- 在任务脚本的最后一步(确认成功后)向该 URL 发一个请求;
- 监控端按任务的计划周期(如每天一次)等待这个"心跳"——超过预期窗口没收到,立即告警。
为什么这样设计?因为失败的方式千奇百怪:脚本报错、机器宕机、cron 服务停了、磁盘满了……不可能穷举每种失败去检测。但"成功"只有一种——所以监控成功的缺席,就覆盖了所有失败模式,包括最阴险的"任务根本没被触发"。
改造你的任务脚本
以数据库备份脚本为例,在成功路径的末尾加一行心跳请求:
#!/usr/bin/env bash
set -o errexit # 任何一步失败即退出,心跳不会发出
date=`date "+%Y-%m-%d_%H:%M:%S"`
file="/dumps/mydb.$date.dump"
pg_dump mydb > "$file"
aws s3 cp "$file" s3://my-backups/
rm "$file"
# 全部成功后才发心跳
curl -fsS "https://你的心跳端点/唯一标识"
要点:
- 心跳放在最后一步,且脚本用
set -e确保失败即退出——中间任何环节挂了,心跳都不会发出; - 心跳请求本身用
-f(失败返回非零)但不要影响主流程; - 配置时设好宽限期(grace period):任务偶尔慢几分钟很正常,宽限期防止误报。
进阶:把执行结果也带上来
更进一步的心跳还能携带元信息:本次处理了多少行、耗时多久、退出码是多少。这些数据让监控从"跑没跑"升级到"跑得对不对"——任务成功执行但处理了 0 行数据,同样值得告警。
通用性:不只 cron
心跳模式适用于一切周期性任务:crontab、systemd timer、K8s CronJob、Windows 任务计划、Airflow DAG、宝塔计划任务……只要任务能发出一个 HTTP 请求,就能纳入监控。对不能改代码的系统任务,也可以用包一层脚本的方式加心跳。
观测云对照
观测云支持用心跳式监控覆盖定时任务:任务完成后向指定地址发请求,监控器按预设周期检查心跳是否按时到达,缺席即按钉钉/企微/飞书/电话分级告警。也可以走另一条路:任务日志统一采集后,对"预期时间窗口内无成功日志"配置无数据告警,两种方式殊途同归。对关键任务,建议心跳 + 日志双保险——前者防静默,后者留现场。
常见问题(FAQ)
Q:心跳监控和传统的"错误日志告警"选哪个?
A:都要。错误日志告警覆盖"跑了但报错",心跳覆盖"根本没跑"(机器宕机、cron 停了、配置丢了)。后者恰恰是最难被发现的失败模式。
Q:任务每小时跑但时长不定,怎么设宽限期?
A:宽限期设为最长预期耗时的 1.5-2 倍。比如任务通常 5 分钟跑完、偶尔 15 分钟,宽限设 20-30 分钟。
Q:K8s CronJob 怎么接?
A:Job 容器里执行完主逻辑后 curl 心跳端点即可;也可以利用 K8s 的 Job 状态指标,监控"预期时间窗口内没有成功的 Job 完成事件"。