一、实现步骤说明#
- 备份准备阶段
- 设置数据库连接信息(数据库名、用户名、密码)
- 配置备份文件存储路径和日志文件路径
- 检查并创建必要的目录结构
- 数据库备份阶段
- 使用mysqldump执行完整数据库导出
- 自动记录备份开始和结束时间到日志文件
- 将SQL文件压缩为tar.gz格式以节省空间
- 清理旧备份阶段
- 自动删除30天前的旧备份文件
- 保留最新的备份文件
- 邮件通知阶段
- 检查备份结果(成功/失败)
- 计算最佳通知时间(当天或次日9点)
- 发送格式化邮件通知,附带备份状态和日志
二、环境准备#
1.安装依赖#
# CentOS/RHEL
sudo yum install mailx
# CentOS/RHEL 8 及以上
sudo yum install s-nail
# Ubuntu/Debian
sudo apt install heirloom-mailxsh2,目录结构示例#
/home/dbback/
├── sqlzip/ # 备份存储(700权限)
├── log/ # 日志目录(755权限)
└── dbbackshell/ # 脚本目录(750权限)sh3.定时任务配置#
# 编辑当前用户的定时任务列表
crontab -e
# 添加定时任务, 每天凌晨1点执行备份
0 1 * * * /home/dbback/dbbackshell/poetize_db_backup.shsh三、脚本代码实现#
1. 备份主脚本(poetize_db_backup.sh)#
#!/bin/bash
# 定义有备份的数据库名
dbname=poetize
# 定义备份数据库时使用的用户名和密码
dbuser=root
dbpasswd=********
# 数据库备份的路径
backuppath=/home/dbback/sqlzip/
# 数据库备份日志文件存储的路径
logfile=/home/dbback/log/poetize_db_backup.log
# 邮件通知脚本路径
email_script=/home/dbback/dbbackshell/send_backup_email.sh
# 获取当前日期, 以当前的时间作为备份的数据库命名
Now=$(date +"%Y-%m-%d")
# 字符串组合生成文件名
dumpfile=poetize_db-$Now
# 检查日志文件是否存在
if [ ! -f "$logfile" ]; then
echo "Log file does not exist, creating..."
# 创建文件所在的目录
mkdir -p $(dirname "$logfile")
# 创建空的日志文件
touch "$logfile"
echo "Log file created."
else
echo "Log file already exists."
fi
# 这个函数用来备份数据库
back_db() {
# 将备份的时间、数据库名存入日志
echo "------"$(date +%Y-%m-%d%t%A%t%T)" Beginning database "${dbname}" backup--------" >>${logfile}
# 备份数据库,如果有错误信息也记入日志。默认utf8编码
#--skip-opt (mysql服务运行时备份,请加此参数,防止表损坏,mysqldump可选参数)
#--quick --force --routines --add-drop-database --add-drop-table (存储过程也会一起备份,mysqldump可选参数)
mysqldump --skip-opt -u${dbuser} -p${dbpasswd} --default-character-set=utf8 --quick --force --routines --add-drop-database --add-drop-table ${dbname} >${backuppath}${dumpfile}.sql 2>> ${logfile}
echo "mysqldump --skip-opt -u${dbuser} -p${dbpasswd} --default-character-set=utf8 --quick --force --routines --add-drop-database --add-drop-table ${dbname} >${backuppath}${dumpfile}.sql 2>> ${logfile}"
# 开始压缩数据文件
echo $(date +%Y-%m-%d%t%A%t%T)" Beginning zip ${backuppath}${dumpfile}.sql" >>${logfile}
# 将备份数据库文件库,并删除先前的SQL文件。如果有错误信息也记入日志。
tar zcvf ${dumpfile}.tar.gz ${dumpfile}.sql && rm ${dumpfile}.sql 2>> ${logfile}
# 将压缩后的文件名存入日志。
echo "backup file name:"${dumpfile}".tar.gz" >>${logfile}
echo -e "-------"$(date +%Y-%m-%d%t%A%t%T)" Ending database "${dbname}" backup-------\n" >>${logfile}
}
# 设置定时发送邮件通知函数
schedule_email() {
# 获取当前时间和今天的9点时间
current_time=$(date +%s)
today_nine_am=$(date -d "today 09:00" +%s)
# 如果当前时间已经过了今天9点,就发送明天的9点通知
if [ $current_time -ge $today_nine_am ]; then
target_time=$(date -d "tomorrow 09:00" +%s)
echo "$(date +'%Y-%m-%d %H:%M:%S') - 今天9点已过,将在明天9点发送通知" >> ${logfile}
else
target_time=$today_nine_am
echo "$(date +'%Y-%m-%d %H:%M:%S') - 将在今天9点发送通知" >> ${logfile}
fi
# 计算需要sleep的秒数
sleep_seconds=$((target_time - current_time))
echo "$(date +'%Y-%m-%d %H:%M:%S') - 将在 $sleep_seconds 秒后(即 $(date -d "+$sleep_seconds seconds") 发送邮件通知" >> ${logfile}
# 使用nohup在后台运行
nohup bash -c "sleep $sleep_seconds && $email_script" >> ${logfile} 2>&1 &
}
# 这个函数用来删除90天前的数据,注意,这个脚本会删除当前目录下所有的早于七天前的文件
rm_oldfile() {
# 查找出当前目录下90天前生成的文件,并将之删除
find /home/dbback/sqlzip/ -type f -mtime +30 -exec rm {} \;
}
# 切换到数据库备份的目录。如果不做这个操作,压缩文件时有可能会错误
cd ${backuppath}
# 运行备份数据函数
back_db
# 运行删除文件函数
rm_oldfile
# 运行发送邮件函数
schedule_emailshell2. 邮件通知脚本(send_backup_email.sh)#
#!/bin/bash
# 配置部分
##############################################
MAIL_TO="touser@example.com" # 收件人邮箱
MAIL_FROM="fromuser@example.com" # 发件人邮箱
MAIL_SUBJECT="数据库备份结果 - $(date +'%Y-%m-%d %H:%M')"
# SMTP配置
SMTP_SERVER="smtp.example.com"
SMTP_PORT="465"
SMTP_USER="user@example.com"
SMTP_PASSWORD="********"
# 路径配置
BACKUP_DIR="/home/dbback/sqlzip/"
LOG_FILE="/home/dbback/log/poetize_db_backup.log"
##############################################
# 获取最新备份文件
LATEST_BACKUP=$(ls -t ${BACKUP_DIR}*.tar.gz 2>/dev/null | head -n 1)
# 检查备份状态并构建消息
if [ -z "$LATEST_BACKUP" ]; then
STATUS_LINE="数据库备份状态【异常】"
DETAIL_LINE="错误详情:未找到任何备份文件!"
ATTACHMENT="$LOG_FILE"
else
BACKUP_TIME=$(stat -c %Y "$LATEST_BACKUP")
CURRENT_TIME=$(date +%s)
TIME_DIFF=$(( (CURRENT_TIME - BACKUP_TIME) / 86400 ))
if [ $TIME_DIFF -gt 1 ]; then
STATUS_LINE="数据库备份状态【异常】"
DETAIL_LINE="错误详情:最新备份已超过1天(${TIME_DIFF}天前)"
ATTACHMENT="$LOG_FILE"
else
STATUS_LINE="数据库备份状态【成功】"
DETAIL_LINE="最新备份文件:$(basename "$LATEST_BACKUP")"
ATTACHMENT="$LATEST_BACKUP"
fi
fi
# 构建邮件内容
MAIL_CONTENT=$(cat <<EOF
${STATUS_LINE}
${DETAIL_LINE}
=== 备份时间 ===
$(date -d @${BACKUP_TIME} +'%Y-%m-%d %H:%M:%S')
EOF
)
# 发送邮件
echo "$MAIL_CONTENT" | mailx -v \
-s "$MAIL_SUBJECT" \
-a ${ATTACHMENT} \
-S smtp="smtps://${SMTP_SERVER}:${SMTP_PORT}" \
-S smtp-auth=login \
-S smtp-auth-user="${SMTP_USER}" \
-S smtp-auth-password="${SMTP_PASSWORD}" \
-S from="${MAIL_FROM}" \
${MAIL_TO}
# 记录发送结果
if [ $? -eq 0 ]; then
echo "$(date +'%Y-%m-%d %H:%M:%S') - 备份通知邮件已发送至 $MAIL_TO" >> "$LOG_FILE"
else
echo "$(date +'%Y-%m-%d %H:%M:%S') - 错误: 无法发送备份通知邮件" >> "$LOG_FILE"
fishell效果如下

四、方案特点#
- 自动化程度高:一键完成备份+清理+通知全流程
- 通知时间智能:自动选择合理时间发送邮件
- 状态判断准确:通过文件检查和时效验证双重确认
- 安全可靠:从存储到传输的全链路安全设计
冷备份的优势:
- 提高数据安全性:就其本质而言,冷备份速度很快,因为它们仅用于复制文件和脱机工作或在关机模式下工作。这使得用户在备份过程中无法访问数据库。这种不可访问性因此成为提高数据安全性的杠杆,自动消除了意外覆盖导致数据变异或彻底删除的可能性。
- 降低数据损坏的可能性:热备份随时可能发生电涌和电力中断。这些可能性使数据和文件容易受到损坏、删除和突变的影响。然而,冷备份大大减少了这些数据损坏的可能性,因为它们被设计为不受可能发生的电涌、电力中断以及病毒和黑客攻击的影响。
- 保证数据的一致性:冷备份时用户会被注销,无法访问数据库。这可确保备份的数据和文件未被更改并保留其原始信息。通过这样做,冷备份保证了数据的一致性。
- 易于恢复:只需将文件复制回来即可轻松恢复到某个时间点。
- 低成本:以低维护成本确保高数据库安全性。
