备份失败不能只靠cron日志发现,因其缺乏指标采集、状态聚合和分级告警能力;需将备份行为转为可观测信号,通过prometheus抓取脚本埋点指标,并在alertmanager中按exit code分级告警。

备份失败为什么不能只靠 cron 日志发现
凌晨三点收到“最近备份大小为 0 字节”的钉钉消息,再去查 cron 日志,已经错过黄金响应窗口。日志里只写 mysqldump exited with status 2,但没告诉你到底是权限错、磁盘满,还是锁表超时——等你登录服务器逐条排查,业务可能已丢失数小时增量。
根本问题在于:cron 不是监控系统,它不采集指标、不聚合状态、不支持分级告警。真正的防御必须把备份行为本身变成可观测信号。
用 Prometheus 抓取 mysqldump 执行结果的关键指标
不要试图让 mysqldump 直接暴露 metrics。正确做法是在备份脚本末尾注入轻量级埋点逻辑,输出结构化状态供 Prometheus 抓取。
- 在备份命令后加一行:
echo "mysql_backup_last_exit_code $(echo $?) | grep -o '^[0-9]*' | head -1" >> /var/lib/prometheus/textfile_collector/backup.prom - 同时记录时间戳和文件大小:
echo "mysql_backup_last_success_timestamp $(date +%s)" >> /var/lib/prometheus/textfile_collector/backup.prom;echo "mysql_backup_last_size_bytes $(stat -c%s "/backup/mydb_$(date -d 'yesterday' +\%F).sql" 2>/dev/null || echo 0)" >> /var/lib/prometheus/textfile_collector/backup.prom - 确保
textfile_collector已启用:Prometheus 的scrape_configs中需包含job_name: 'textfile'和static_configs指向该目录 - 注意权限:
prometheus用户必须能读/var/lib/prometheus/textfile_collector/下的文件,否则指标为空
Alertmanager 配置中区分“可恢复”与“需人工介入”的告警
同一类失败,不同 exit code 意味着完全不同的处理路径。硬编码统一告警只会制造噪音。
- 对
mysql_backup_last_exit_code == 2(连接拒绝)或== 11(I/O 错误)触发快速告警,group_interval: 1m,路由到 oncall 群,因为大概率是临时抖动 - 对
mysql_backup_last_exit_code == 3(权限/表不存在)或== 4(无效参数)走另一条 route,repeat_interval: 24h,仅发邮件给 DBA,附带SHOW GRANTS FOR 'backup_user'@'%'命令建议 - 当
mysql_backup_last_success_timestamp 且 <code>mysql_backup_last_size_bytes == 0时,说明连续两天失败,必须升级为 P1 级别,触发企微机器人自动 @ 主管 + 创建 Jira 工单 - 避免误报:在 Alertmanager 的
inhibit_rules中加一条:若node_filesystem_avail_bytes{mountpoint="/backup"} 同时触发,则抑制所有备份失败告警——先解决磁盘问题,再谈重试
真正容易被忽略的链路断点:备份脚本自身不可观测
很多人配好了 Prometheus 和 Alertmanager,却忘了最前端——备份脚本是否真的执行了?有没有被 crond 跳过?有没有因 PATH 环境变量缺失导致 mysqldump 找不到?
必须在脚本开头加:echo "mysql_backup_script_start_timestamp $(date +%s)" > /var/lib/prometheus/textfile_collector/backup.prom,并在结尾加 echo "mysql_backup_script_end_timestamp $(date +%s)" >> /var/lib/prometheus/textfile_collector/backup.prom。这样就能用 rate(mysql_backup_script_start_timestamp[1h]) 确认脚本是否按时触发,而不是靠日志里有没有 “Started backup” 字样来赌运气。











