数据库自动异地备份脚本

以下是一个可以自动远程备份本地MySQL数据库的脚本。这个脚本使用mysqldump来备份数据库,并通过scp命令将备份文件上传到远程服务器。

实现目的,自动备份数据库到另一台服务器,自动删除过期备份,自动重试,错误记录等等。

当然,这个脚本稍稍修改一下,也可以备份其他,比如 /var/www/website 网站文件, /etc/nginx nginx配置文件等等。

脚本如下:

vi /path/to/your/backup_script.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#!/bin/bash

# -------------- 配置部分 ---------------- #

# MySQL数据库凭证(本地服务器)
MYSQL_USER="root" # 数据库用户名
MYSQL_PASS="your_mysql_password" # 数据库密码
MYSQL_DB="your_database_name" # 数据库名(或者使用--all-databases来备份所有数据库)

# 本地临时备份目录
LOCAL_BACKUP_DIR="/tmp/mysql-backup" # 本地备份存储目录
LOG_FILE="/var/log/mysql-remote-backup.log" # 日志文件

# 远程备份服务器的连接信息
REMOTE_USER="backupuser" # 远程服务器的用户名
REMOTE_HOST="your.remote-server.com" # 远程服务器的主机名或IP
REMOTE_PORT="22" # 远程服务器的SSH端口
REMOTE_DIR="/backups/mysql" # 远程备份存储目录

# 备份文件保留天数
LOCAL_RETENTION_DAYS=3 # 删除本地备份文件(超过3天)
REMOTE_RETENTION_DAYS=7 # 删除远程备份文件(超过7天)

# -------------- 脚本开始 ----------------- #

# 获取当前时间作为备份文件名的一部分
DATE=$(date +%F-%H%M%S)
BACKUP_NAME="${MYSQL_DB}-backup-${DATE}.sql" # 备份文件名(不压缩)
ARCHIVE_NAME="${BACKUP_NAME}.tar.gz" # 压缩后的备份文件名

# 创建本地备份目录(如果不存在的话)
mkdir -p $LOCAL_BACKUP_DIR

# 记录备份开始时间
echo "[$(date)] 开始备份 MySQL 数据库..." | tee -a $LOG_FILE

# 执行 MySQL 数据库备份
mysqldump -u$MYSQL_USER -p$MYSQL_PASS $MYSQL_DB > $LOCAL_BACKUP_DIR/$BACKUP_NAME

# 如果备份失败,则记录错误并退出
if [ $? -ne 0 ]; then
echo "[$(date)] MySQL 数据库备份失败!" | tee -a $LOG_FILE
exit 1
fi

# 压缩备份文件
tar -czf $LOCAL_BACKUP_DIR/$ARCHIVE_NAME -C $LOCAL_BACKUP_DIR $BACKUP_NAME
# 删除未压缩的备份文件
rm -f $LOCAL_BACKUP_DIR/$BACKUP_NAME

# 使用 SCP 将备份文件上传到远程服务器
# 重试机制:如果第一次上传失败,尝试重试最多3次
RETRY_COUNT=0
MAX_RETRIES=3
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
scp -P $REMOTE_PORT $LOCAL_BACKUP_DIR/$ARCHIVE_NAME ${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DIR}/
if [ $? -eq 0 ]; then
echo "[$(date)] 备份文件成功上传到远程服务器。" | tee -a $LOG_FILE
break
else
echo "[$(date)] 第$((RETRY_COUNT+1))次尝试上传失败,正在重试..." | tee -a $LOG_FILE
RETRY_COUNT=$((RETRY_COUNT+1))
if [ $RETRY_COUNT -eq $MAX_RETRIES ]; then
echo "[$(date)] 上传失败次数达到最大重试次数,备份上传失败。" | tee -a $LOG_FILE
exit 1
fi
fi
done

# 删除本地过期的备份文件
echo "[$(date)] 正在删除超过 $LOCAL_RETENTION_DAYS 天的本地备份文件..." | tee -a $LOG_FILE
find $LOCAL_BACKUP_DIR -type f -mtime +$LOCAL_RETENTION_DAYS -delete

# 删除远程过期的备份文件
echo "[$(date)] 正在删除远程服务器上超过 $REMOTE_RETENTION_DAYS 天的备份文件..." | tee -a $LOG_FILE
ssh -p $REMOTE_PORT ${REMOTE_USER}@${REMOTE_HOST} "find ${REMOTE_DIR} -type f -mtime +${REMOTE_RETENTION_DAYS} -delete"

# 记录备份完成时间
echo "[$(date)] MySQL 数据库备份完成。" | tee -a $LOG_FILE

exit 0

脚本结构说明:

  1. 配置部分

    • MySQL数据库凭证:你可以设置数据库的用户名、密码以及数据库名(或者选择备份所有数据库)。
    • 本地备份目录:定义了临时存储备份文件的本地目录。
    • 远程服务器信息:定义了备份文件传输到的远程服务器和目录,并且提供了SSH端口和用户名。
    • 保留策略:你可以设置本地和远程备份文件的保留天数,超出天数的备份文件会被删除。
  2. 脚本执行流程

    • 创建本地备份目录:确保备份目录存在。
    • 备份MySQL数据库:使用mysqldump命令备份指定的数据库(如果需要备份所有数据库,可以修改为--all-databases)。
    • 压缩备份文件:将备份文件进行压缩(使用tar.gz格式),然后删除未压缩的备份文件。
    • 上传到远程服务器:通过scp命令将压缩后的备份文件上传到远程服务器。
    • 删除本地过期备份:通过find命令删除本地超过指定天数的备份文件。
    • 删除远程过期备份:通过ssh连接远程服务器并执行删除远程过期备份的命令。
  3. 日志记录

    • 使用tee命令将日志同时输出到控制台和日志文件(/var/log/mysql-remote-backup.log)。每个操作的开始、结束及错误信息都会被记录。

设置定时任务:

你可以通过crontab -e添加定时任务,让备份脚本每天自动执行:

1
0 3 * * * /path/to/your/backup_script.sh

这样,脚本会每天凌晨3点执行一次,自动备份并清理过期文件。

最后,提醒一下,如果两台服务器都用ssh key登陆的话,可以省去很多不必要的步骤。