mysql备份任务如果只写个crontab定时执行mysqldump,一旦磁盘满了、权限错了或者实例连不上,失败信息只会躺在日志里无人问津。要把报警通知做扎实,思路其实很直接:在备份命令执行后立即判断退出状态,非0就触发通知逻辑。通知可以走邮件,也可以走钉钉群机器人,两种通道不冲突,甚至可以并行。

一、备份脚本基础结构与退出码捕获
任何报警机制的前提是能准确知道备份是否成功。在shell中,上一条命令的返回码存放在特殊变量$?里,0表示成功,非0表示失败。我们写备份脚本时,不能让mysqldump的输出被吞掉,同时要保留它的返回状态。
下面这段脚本演示了最基本的框架:先执行dump,再判断$?,根据结果设置变量,后续通知环节直接读这个变量。注意mysqldump加了--single-transaction避免锁表,实际生产可再加--routines和--events。
#!/bin/bash # 基础备份脚本框架 BACKUP_DIR=/data/backup DATE=$(date +%Y%m%d_%H%M%S) DB_NAME=app_db FILE=$BACKUP_DIR/$DB_NAME_$DATE.sql.gz mysqldump -u backup_user -p'secret' --single-transaction $DB_NAME | gzip > $FILE STATUS=$? if [ $STATUS -eq 0 ]; then RESULT="备份成功: $FILE" else RESULT="备份失败: 退出码 $STATUS" fi echo $RESULT
这个框架把成功和失败的统一描述放进了RESULT变量,后面的邮件和钉钉函数只要接收这个字符串就行。把通知和备份解耦,脚本更好维护。
需要提醒的是,管道右侧的gzip如果失败,左边mysqldump的返回码会被覆盖,所以更严谨的做法是用pipefail或者分开写临时文件再压缩。不过对报警而言,只要最终文件没生成或大小为0,我们就认为失败,后面会加文件校验来补强。
二、集成邮件报警通知
邮件通知的优势在于可留痕、可转发、不依赖第三方IM。服务器上通常装了mailx或者mutt,也可以借助公网SMTP中继。最轻量的方式是用mailx直接发,前提是/etc/mail.rc配好了SMTP账号。
我们在脚本里加一个send_mail函数,接收主题和正文。如果备份失败,正文里带上失败时间和可能的错误片段,方便事后排查。下面示例用mailx通过外部SMTP发送,密码等敏感信息建议用变量从环境文件读取。
send_mail() {
local subject="$1"
local body="$2"
echo "$body" | mailx -s "$subject" -S smtp=smtp://smtp.ipipp.com:25
-S smtp-auth=login -S smtp-auth-user=alert@ipipp.com
-S smtp-auth-password='mailpass' -S from=alert@ipipp.com
admin@ipipp.com
}
# 在备份判断后调用
if [ $STATUS -eq 0 ]; then
send_mail "MySQL备份成功" "$RESULT"
else
send_mail "MySQL备份失败" "$RESULT"
fi
邮件方案的缺点是实时性一般,且如果SMTP配置错误,报警本身也会失败。因此生产环境建议邮件和钉钉双发,互为备份。另外要注意,有些云厂商禁用了25端口,需要改用465并加-S smtp-use-starttls之类的参数。
对于没有公网SMTP的场景,也可以让本机postfix relay到内部邮件网关,只要能通就行。关键是要先手动跑一次发信测试,确认不会进垃圾箱,且收件人能及时收到。
三、集成钉钉机器人Webhook提醒
钉钉群机器人通过Webhook接收POST请求,消息体是JSON。创建机器人后会得到一个类似https://oapi.dingtalk.com/robot/send?access_token=xxx的地址,我们把它存到变量里,用curl推送即可。
钉钉消息类型常用text,内容里可以@指定人。下面函数把备份结果作为文本发出,并在失败时@管理员。注意JSON里的双引号要转义,整体用单引号包住避免shell展开。
DING_WEBHOOK="https://oapi.dingtalk.com/robot/send?access_token=your_token"
send_ding() {
local text="$1"
local at=""
if [ $STATUS -ne 0 ]; then
at='"at": {"atMobiles":["13800138000"], "isAtAll": false},'
fi
curl -s -X POST "$DING_WEBHOOK"
-H 'Content-Type: application/json'
-d '{"msgtype": "text", '"$at"' "text": {"content": "'"$text"'"}}'
}
# 调用
send_ding "MySQL备份任务反馈: $RESULT"
钉钉提醒的延迟通常在秒级,非常适合值班盯盘。但access_token泄露会被滥发,所以群机器人最好单独建群,并开启“仅允许白名单IP”能力。如果公司网络出口IP固定,务必配置,防止他人拿token炸群。
除了text类型,钉钉还支持markdown和actionCard,可以把备份大小、耗时、服务器名用表格展现。不过报警场景越简单越好,text最稳,不容易因格式拼错导致整个通知失败。
四、完整脚本与排错建议
把前面几块拼起来,就是一个带双通道报警的备份脚本。我们额外加了备份文件大小检查,防止dump出来是空文件却报成功。同时把日志写到本地,方便比对通知内容。
#!/bin/bash
set -o pipefail
BACKUP_DIR=/data/backup
DATE=$(date +%Y%m%d_%H%M%S)
DB_NAME=app_db
FILE=$BACKUP_DIR/${DB_NAME}_$DATE.sql.gz
DING_WEBHOOK="https://oapi.dingtalk.com/robot/send?access_token=your_token"
LOG=/var/log/mysql_backup.log
mysqldump -u backup_user -p'secret' --single-transaction $DB_NAME | gzip > $FILE
STATUS=$?
if [ $STATUS -eq 0 ] && [ -s $FILE ]; then
RESULT="备份成功: $FILE 大小 $(du -h $FILE | cut -f1)"
else
RESULT="备份失败: 退出码 $STATUS 或文件为空"
fi
echo "$(date) $RESULT" >> $LOG
# 邮件
echo "$RESULT" | mailx -s "MySQL备份通知" admin@ipipp.com
# 钉钉
AT=''
if [ $STATUS -ne 0 ] || [ ! -s $FILE ]; then
AT='"at": {"isAtAll": true},'
fi
curl -s -X POST "$DING_WEBHOOK" -H 'Content-Type: application/json'
-d '{"msgtype":"text",'"$AT"' "text":{"content":"'"$RESULT"'"}}'
排错时最常见的问题是curl命令在crontab里找不到,因为环境变量和交互终端不同。建议在脚本里用绝对路径/usr/bin/curl,或者在crontab里先source环境文件。另一个坑是mailx参数在不同发行版名字略有差异,CentOS和Ubuntu的mailx可能不是一个包,要实测。
最后,报警不是配完就完事,要定期做故障演练:手动改错密码让备份失败一次,看邮件和钉钉是否都收到。只有演练过的报警才叫报警,否则只是心理安慰。
mysql_backupemail_alertdingtalk_webhook修改时间:2026-08-04 04:09:16