mysqldump失败应检查$?而非依赖&&链;禁用--force;用head -c1验空;cron中显式设path并用mail+2>&1发信;钉钉传错情需过滤密码、提取关键信息;备份后须抽样恢复验证。

mysqldump 失败时怎么让脚本主动报错
备份脚本静默失败是报警失效的第一原因。mysqldump 本身退出码(exit code)就是判断依据:成功为 0,权限不足、连接失败、表不存在等都会返回非零值(常见如 2、3、11)。但很多人直接用 && 连接后续命令,一旦 mysqldump 被重定向了 stderr 或加了 --force,就可能掩盖真实失败。
实操建议:
- 始终检查
$?,别依赖命令链;备份后立刻用if [ $? -ne 0 ]; then ...分支处理 - 去掉
--force——它会让 dump 忽略部分错误继续执行,导致生成空文件却返回0 - 加
--single-transaction时注意:如果库含 MyISAM 表,该选项无效,且不会报错,需单独用SHOW TABLE STATUS检查引擎类型 - 用
head -c 1验证输出文件是否为空比单纯看文件大小更可靠(避免压缩工具写入头信息)
Linux cron 里发邮件为什么总收不到
cron 环境变量极简,PATH 不含 /usr/sbin:/sbin,导致 mail、sendmail 找不到;同时 MAILTO 只转发 stdout/stderr,而 mysqldump 的关键错误常在 stderr,若被重定向就漏掉。
实操建议:
- 在 crontab 中显式声明
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin - 不要只靠
MAILTO=xxx,改用脚本内调用mail或ssmtp,并把2>&1显式捕获 - 测试时先用
echo "test" | mail -s "cron test" you@example.com确认 MTA 可用 - 避免用
mutt——它依赖交互式配置,在 cron 下易卡住;mailx更轻量稳定
钉钉机器人怎么传 MySQL 错误详情又不暴露密码
直接把 mysqldump 命令或完整报错日志发到钉钉,很可能带出 -pYourPass123 或连接串里的密码。钉钉机器人 POST 的 content 字段明文传输,没加密。
实操建议:
- 用
--defaults-file替代命令行密码参数,把账号密码写进~/.my.cnf并设chmod 600 - 错误内容提取前先过一遍
sed 's/-p[^[:space:]]*//g; s/password=[^[:space:]]*//g' - 钉钉消息里只放关键信息:时间、实例 IP、库名、
mysqldump退出码、截取前 3 行 stderr(用head -n 3) - Webhook URL 别硬编码在脚本里,用环境变量或独立配置文件加载,避免 git 提交泄露
备份文件校验通过但恢复失败,报警没覆盖这个环节
很多报警只盯“dump 是否完成”,但 mysqldump 生成的 SQL 文件可能语法错误(比如触发器含未转义的换行)、字符集不匹配、或用了目标 MySQL 版本不支持的语法(如 JSON_TABLE),导致恢复时报错,而此时备份任务早已标记“成功”。
实操建议:
- 定期(比如每周)抽样做快速恢复验证:用
mysql -e "CREATE DATABASE recover_test"+mysql recover_test ,检查退出码 - 在 dump 命令中加
--skip-triggers --skip-routines分离导出,降低恢复复杂度;后续单独处理存储过程 - 用
grep -q "ERROR\|Warning" &1)类方式预检 SQL 文件头部兼容性 - 别省略
--set-gtid-purged=OFF(MySQL 5.7+)——否则 GTID 环境下恢复会直接失败,且错误不明显
真正难的不是发通知,是让通知反映真实风险。比如一个因磁盘满导致的 dump 截断,和一个因主从延迟导致的 --single-transaction 失效,表现都是文件变小,但根因和应对完全不同。报警字段里得带上下文,而不是只写“备份失败”。











