备份任务每天定时跑,日志里一行错误都没有,恢复那天 gunzip 直接报 unexpected end of file,打开一看文件是 0 字节,当月七份全是空的。日志里能对上时间点,这种反而好排。
写的是 mysqldump 管道接 gzip,mysqldump 失败之后的退出码被管道末尾的 gzip 吞掉,脚本只看最后一个命令的返回值,于是当成成功,这个坑平时很难发现。这一点先确认清楚,后面就不用反复试。
set -o pipefail mysqldump --single-transaction -uroot -p db \ | gzip > /backup/db-$(date +%F).sql.gz gzip -t /backup/db-$(date +%F).sql.gz && echo ok
「备份文件 0 字节」确认了原因之后,改动尽量只碰那一处,顺手改的东西后面最容易出问题。先做最小复现,能稳定跑出来的问题,排查成本会低一个数量级。
别只看报错的最后一行,往上看几行,真正的起因通常在上面。
处理上按这个顺序:脚本开头加 pipefail,让管道里任何一环失败都返回非零;导出后立刻用 gzip -t 校验一遍完整性,不要等到恢复时才发现;文件小于阈值就直接发告警,不要在日志里写成功状态。
结果对不对很好判断,故意让 mysqldump 失败一次,脚本能返回非零并触发告警,正常包过 gzip 校验。
