该脚本实现mysql数据库每日自动备份与过期清理:支持多库导出、日期命名压缩、磁盘空间检查、详细日志记录及幂等性保障,保留指定天数备份并自动删除旧文件。

下面是一个实用、健壮的 Shell 脚本,用于每日自动备份 MySQL 数据库,并按保留天数清理过期备份文件。它支持多数据库、自定义路径、错误检测与日志记录,适合部署在 Linux 服务器(如 CentOS / Ubuntu)的 cron 中运行。
核心功能说明
✅ 自动导出指定数据库(支持单个或多个)
✅ 按日期生成压缩备份(.sql.gz 格式)
✅ 保留指定天数的历史备份(如 7 天),自动删除更早文件
✅ 备份前检查磁盘空间(避免写满根分区)
✅ 记录详细日志(成功/失败/跳过/清理动作)
✅ 避免重复备份同一天文件(幂等性)
完整可执行脚本(保存为 db_backup.sh)
#!/bin/bash
# MySQL 数据库自动备份 + 历史清理脚本
# 使用前请修改下方 CONFIG 区域
########## CONFIG START ##########
DB_USER="backup_user" # MySQL 用户名(建议专用只读账号)
DB_PASS="your_secure_password" # 密码(生产环境建议用 ~/.my.cnf 避免明文)
DB_HOST="localhost" # MySQL 地址
DB_NAMES=("app_db" "blog_db") # 要备份的数据库名数组(支持多个)
BACKUP_DIR="/data/backups/mysql" # 备份存储目录(需提前创建并授权)
RETAIN_DAYS=7 # 保留最近 N 天的备份
LOG_FILE="/var/log/db_backup.log" # 日志路径
MYSQL_CMD="/usr/bin/mysqldump" # mysqldump 路径(可用 which mysqldump 确认)
GZIP_CMD="/bin/gzip" # gzip 路径
########## CONFIG END ##########
# 日志函数
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}
# 检查必要命令是否存在
for cmd in $MYSQL_CMD $GZIP_CMD; do
if ! command -v "$cmd" &> /dev/null; then
log "ERROR: $cmd not found. Aborting."
exit 1
fi
done
# 创建备份目录(若不存在)
mkdir -p "$BACKUP_DIR"
if [[ $? -ne 0 ]]; then
log "ERROR: Failed to create backup directory $BACKUP_DIR"
exit 1
fi
# 检查磁盘空间(剩余空间
FREE_SPACE=$(df "$BACKUP_DIR" | tail -1 | awk '{print $4}')
if [[ $FREE_SPACE -lt 2097152 ]]; then # 单位 KB,2GB ≈ 2097152 KB
log "WARNING: Less than 2GB free space on $(df -h "$BACKUP_DIR" | tail -1 | awk '{print $1}'). Skipping backup."
exit 0
fi
# 生成今日时间戳(格式:YYYYMMDD)
TODAY=$(date +%Y%m%d)
# 遍历每个数据库执行备份
for DB in "${DB_NAMES[@]}"; do
BACKUP_FILE="$BACKUP_DIR/${DB}_$TODAY.sql.gz"
# 跳过已存在的当日备份(防止重复执行)
if [[ -f "$BACKUP_FILE" ]]; then
log "SKIP: Backup for $DB already exists today ($BACKUP_FILE)"
continue
fi
log "START: Backing up database '$DB'..."
# 执行 mysqldump + gzip 流式压缩(不生成中间 .sql 文件)
if $MYSQL_CMD -h"$DB_HOST" -u"$DB_USER" -p"$DB_PASS" --single-transaction --routines --triggers "$DB" 2>/tmp/dump_err | $GZIP_CMD > "$BACKUP_FILE"; then
if [[ -s "$BACKUP_FILE" ]]; then
log "SUCCESS: $DB backed up → $BACKUP_FILE ($(du -h "$BACKUP_FILE" | cut -f1))"
else
log "ERROR: $BACKUP_FILE is empty. Check MySQL user permissions or disk quota."
rm -f "$BACKUP_FILE"
fi
else
ERR_MSG=$(cat /tmp/dump_err 2>/dev/null | head -n 3 | tr '\n' ' ')
log "ERROR: Failed to dump $DB: $ERR_MSG"
rm -f "$BACKUP_FILE"
fi
rm -f /tmp/dump_err
done
# 清理过期备份(保留 RETAIN_DAYS 天)
log "CLEANUP: Removing backups older than $RETAIN_DAYS days..."
find "$BACKUP_DIR" -name "*.sql.gz" -type f -mtime +$RETAIN_DAYS -delete -print | while read f; do
log "REMOVED: $f"
done
log "FINISHED: Daily backup task completed."
部署与使用步骤
-
权限设置:运行
chmod +x db_backup.sh -
MySQL 权限准备:创建专用用户(最小权限),例如:
CREATE USER 'backup_user'@'localhost' IDENTIFIED BY 'strong_pwd';<br> GRANT LOCK TABLES, SELECT ON *.* TO 'backup_user'@'localhost';<br> FLUSH PRIVILEGES;
-
安全优化(推荐):将密码移至
~/.my.cnf,并设权限chmod 600 ~/.my.cnf,内容如下:[client]<br> user=backup_user<br> password=your_secure_password<br> host=localhost
然后脚本中删掉-p"$DB_PASS"和-u"$DB_USER"参数,仅留-h"$DB_HOST" -
添加定时任务:每天凌晨 2:30 执行,编辑 crontab:
30 2 * * * /path/to/db_backup.sh >> /dev/null 2>&1 -
验证日志:定期检查
$LOG_FILE,确认 SUCCESS 行和 REMOVED 记录是否正常
常见问题与增强建议
-
备份失败无报警? 可在脚本末尾添加邮件通知(如
echo "Backup OK" | mail -s "DB Backup Success" admin@example.com),或接入企业微信/钉钉机器人 -
大库导出慢/超时? 在
mysqldump命令后加--max-allowed-packet=512M --net-buffer-length=1M并调高 MySQL 的wait_timeout -
想加密备份文件? 可用
gpg替代gzip,例如:... | gpg --symmetric --cipher-algo AES256 -o "$BACKUP_FILE.gpg" -
跨服务器备份? 备份完成后用
rsync或scp同步到异地 NAS 或对象存储(如 AWS S3、MinIO)











