博客 / Others/ 终极版rsync-VPS每日定时同步自动备份方法

终极版rsync-VPS每日定时同步自动备份方法

终极版rsync-VPS每日定时同步自动备份方法

前言

本文介绍一种使用 rsync 实现 VPS 间每日定时自动备份的方案。假设需要备份的网站所在服务器为 VPS A,用于备份的服务器为 VPS B,系统均为 CentOS。目标是让 VPS B 定时拉取 VPS A 上的网站文件和数据库备份。

一、VPS A(源服务器)部署

VPS A 作为 rsync 服务端,需要配置 rsync 守护进程,并设置 MySQL 自动备份脚本。

1. 安装 rsync

使用 yum 安装 rsync:

yum -y install rsync

将 rsync 加入开机启动(适用于使用 systemd 前的 CentOS 版本):

echo 'rsync --daemon' >> /etc/rc.d/rc.local

注意:现代 CentOS/RHEL 7+ 系统通常使用 systemd,更推荐使用 systemctl enable rsyncd 来启用服务(如果使用系统服务的话)。本文以传统 daemon 模式为例。

2. 设置 rsync 认证密码

创建密码文件,格式为“用户名:密码”:

echo '你的用户名:你的密码' > /etc/rsyncd.scrt
chmod 600 /etc/rsyncd.scrt

此处设置的用户名和密码将在 VPS B 上连接时使用。

3. 配置 rsync 服务

编辑配置文件 /etc/rsyncd.conf

uid = root
gid = root
use chroot = no
read only = yes
max connections = 10

port = 873
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsync.lock
#log file = /var/log/rsync.log # 可选,是否记录日志
log format = %t %a %m %f %b
syslog facility = local3
timeout = 300

[www]
path = /var/www/
comment = 网站数据
ignore errors
read only = yes
list = no
auth users = andy
secrets file = /etc/rsyncd.scrt
#exclude = cache/ # 不需要备份的目录,也可使用 exclude from 文件
# 使用 exclude from 文件来定义排除列表
exclude from = /etc/rsync_exclude.txt
hosts allow = 备份服务器的IP
hosts deny = *

配置说明:

  • [www]:模块名,客户端连接时指定。
  • path:要同步的源目录。
  • auth users:允许认证的用户名。
  • hosts allow:务必替换为 VPS B 的真实 IP 地址,以增强安全性。

4. 定义排除列表

创建排除文件 /etc/rsync_exclude.txt,列出不需要备份的目录(相对 path 的路径),每行一个:

youquso.com/new/cache/
youquso.com/manual/

5. 创建 rsync 重启脚本

创建脚本 /root/rsyncd_restart.sh,用于重启 rsync 守护进程:

#!/bin/bash
kill -9 `cat /var/run/rsyncd.pid`
rm -f /var/run/rsyncd.pid
rm -f /var/run/rsync.lock
rsync --daemon

赋予执行权限:

chmod 600 /root/rsyncd_restart.sh
chmod +x /root/rsyncd_restart.sh

之后可通过 /root/rsyncd_restart.sh 重启服务。

6. 配置 MySQL 自动备份脚本

创建脚本 /root/mysql_backup.sh,用于备份多个数据库,并自动清理旧备份:

#!/bin/bash

# 以下配置信息请根据实际情况修改
mysql_user="USER" # MySQL备份用户
mysql_password="PASSWORD" # 对应用户的密码
mysql_host="localhost"
mysql_port="3306"
mysql_charset="utf8mb4" # 建议使用 utf8mb4
backup_db_arr=("db1" "db2") # 要备份的数据库,多个用空格隔开
backup_location=/var/www/mysql # 备份存放目录,末尾不要带"/"
expire_backup_delete="ON" # 是否开启过期备份删除 ON为开启 OFF为关闭
expire_days=3 # 过期天数,expire_backup_delete开启时有效

# 以下部分一般无需修改
backup_time=`date +%Y%m%d%H%M`
backup_Ymd=`date +%Y-%m-%d`
backup_3ago=`date -d '3 days ago' +%Y-%m-%d`
backup_dir=$backup_location/$backup_Ymd
welcome_msg="MySQL backup start."

# 判断MySQL是否运行
mysql_ps=`ps -ef |grep mysqld |grep -v grep |wc -l`
mysql_listen=`netstat -an |grep LISTEN |grep ":$mysql_port" |wc -l`
if [[ $mysql_ps -eq 0 ]] || [[ $mysql_listen -eq 0 ]]; then
    echo "ERROR: MySQL is not running! Backup stopped."
    exit 1
else
    echo $welcome_msg
fi

# 测试数据库连接
mysql -h$mysql_host -P$mysql_port -u$mysql_user -p$mysql_password -e "SELECT 1" > /dev/null 2>&1
if [ $? -ne 0 ]; then
    echo "ERROR: Can't connect to MySQL server! Backup stopped."
    exit 1
else
    echo "MySQL connection OK. Starting backup..."
fi

# 开始备份数据库
if [ "${#backup_db_arr[@]}" -gt 0 ]; then
    mkdir -p $backup_dir
    for dbname in "${backup_db_arr[@]}"
    do
        echo "Backing up database: $dbname"
        mysqldump -h$mysql_host -P$mysql_port -u$mysql_user -p$mysql_password 
        --single-transaction --routines --triggers --default-character-set=$mysql_charset $dbname | gzip > $backup_dir/${dbname}-${backup_time}.sql.gz
        if [ $? -eq 0 ]; then
            echo "Database $dbname backed up to $backup_dir/${dbname}-${backup_time}.sql.gz"
        else
            echo "ERROR: Failed to backup database $dbname"
        fi
    done
else
    echo "ERROR: No database specified for backup."
    exit 1
fi

# 清理过期备份
if [ "$expire_backup_delete" == "ON" ] && [ -n "$backup_location" ]; then
    find $backup_location -type d -mtime +$expire_days -exec rm -rf {} ; 2>/dev/null
    echo "Expired backups older than $expire_days days have been deleted."
fi

echo "All databases backed up successfully."

赋予脚本执行权限:

chmod 600 /root/mysql_backup.sh
chmod +x /root/mysql_backup.sh

加入 crontab,每天 00:00 执行:

0 0 * * * /root/mysql_backup.sh

至此,VPS A 上的部署完成。网站文件将通过 rsync 模块提供,数据库备份文件将生成在 /var/www/mysql/ 目录下,该目录也在 rsync 同步路径内。

二、VPS B(备份服务器)部署

VPS B 作为 rsync 客户端,定时从 VPS A 拉取数据。

1. 安装 rsync

yum -y install rsync

客户端无需常驻服务,因此不需要加入开机启动。

2. 设置 rsync 密码文件

创建仅包含密码的文件(注意:不是“用户名:密码”,只有密码):

echo '你在A上设置的密码' > /etc/rsync.pass
chmod 400 /etc/rsync.pass

3. 测试同步

创建本地存储目录:

mkdir -p /var/rsync/

执行测试同步命令:

rsync -avzP --delete --password-file=/etc/rsync.pass 用户名@VPS_A_IP::www /var/rsync/website_backup/

命令参数说明:

  • -avzP: 归档模式、显示详情、压缩传输、显示进度。
  • --delete: 让目标目录与源目录严格一致,源端删除的文件在目标端也会被删除。
  • --password-file: 指定密码文件路径,避免交互输入。
  • 用户名@VPS_A_IP::www: 连接 VPS A 的 rsync 服务,使用 www 模块。用户名需与 VPS A 密码文件中定义的一致。
  • 最后参数是本地存储路径。

4. 加入定时任务

编辑 crontab,设定每天 00:30 执行同步(假设 MySQL 备份在 00:00 完成):

30 0 * * * rsync -avzP --delete --password-file=/etc/rsync.pass 用户名@VPS_A_IP::www /var/rsync/website_backup/ > /dev/null 2>&1

输出重定向到 /dev/null 可避免产生不必要的日志邮件。

总结与扩展

通过以上步骤,已经建立了一个从 VPS A 到 VPS B 的自动备份系统,涵盖了网站文件和数据库。

为了进一步提升数据安全性,可以考虑增加一个“VPS C”,让 C 从 B 再次同步,形成异地双重备份。其配置方法与 VPS B 从 A 拉取类似,只需将源地址改为 VPS B 的 IP 并配置相应的 rsync 服务端即可。

重要提示

  • 确保防火墙开放了 VPS A 的 873 端口(或自定义的 rsync 端口)。
  • 密码文件需严格设置权限,防止泄露。
  • 定期检查备份日志和备份文件的完整性。
  • 对于现代 Linux 发行版,建议研究使用 systemd service 或 timer 来管理 rsync 服务与定时任务。

发表评论

您的邮箱不会公开。必填项已用 * 标注。