海外服务器数据备份完整策略:rsync + Rclone + 对象存储三层备份方案实操
数据无价,备份无悔。硬盘故障、误操作、勒索软件攻击——这些风险在没有备份的情况下都是灾难性的。本文为香港 VPS 设计一套三层备份架构:本地快照 + 异地同步 + 对象存储,覆盖从分钟级到月级的完整数据保护。
一、三层备份架构设计
| 备份层 | 工具 | 存储位置 | 保留周期 | 主要防护 |
|---|---|---|---|---|
| 第一层:本地增量 | rsync | 本机另一分区 | 7天 | 误操作、文件损坏 |
| 第二层:异地同步 | Rclone | 另一台 VPS | 14天 | 机房故障、硬件损坏 |
| 第三层:云端归档 | Rclone | Cloudflare R2 / S3 | 90天 | 勒索软件、完全丢失 |
二、第一层:rsync 本地增量备份
<code">mkdir -p /backup/{daily,weekly,mysql,configs}
# 创建主备份脚本
cat > /usr/local/bin/backup-local.sh << 'SCRIPT' #!/bin/bash set -euo pipefail DATE=$(date +%Y%m%d) BACKUP_ROOT="/backup" LOG="/var/log/backup.log" log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a $LOG; } # ── 1. 网站文件增量备份 ── log "开始备份网站文件..." rsync -avz --delete \ --exclude='*.log' \ --exclude='*.tmp' \ --exclude='wp-content/cache/' \ /var/www/ \ $BACKUP_ROOT/daily/www-$DATE/ log "网站文件备份完成" # ── 2. MySQL 全量备份 ── log "开始备份 MySQL..." mkdir -p $BACKUP_ROOT/mysql # 逐库备份(方便单库恢复) mysql -uroot -p"$MYSQL_ROOT_PASSWORD" -e "SHOW DATABASES;" \ | grep -Ev "Database|information_schema|performance_schema|sys" \ | while read db; do mysqldump -uroot -p"$MYSQL_ROOT_PASSWORD" \ --single-transaction \ --routines \ --triggers \ "$db" | gzip > $BACKUP_ROOT/mysql/${db}_${DATE}.sql.gz
log "已备份数据库: $db"
done
# ── 3. 配置文件备份 ──
log "备份配置文件..."
tar -czf $BACKUP_ROOT/configs/configs-$DATE.tar.gz \
/etc/nginx \
/etc/mysql \
/etc/php \
/etc/letsencrypt \
/etc/crontab \
/opt/monitoring 2>/dev/null || true
# ── 4. 清理 7 天前的旧备份 ──
find $BACKUP_ROOT/daily -maxdepth 1 -type d -mtime +7 -exec rm -rf {} +
find $BACKUP_ROOT/mysql -name "*.sql.gz" -mtime +7 -delete
find $BACKUP_ROOT/configs -name "*.tar.gz" -mtime +7 -delete
log "本地备份完成 ✓"
SCRIPT
chmod +x /usr/local/bin/backup-local.sh三、第二层:Rclone 安装与配置
<code"># 安装 Rclone curl https://rclone.org/install.sh | bash rclone version
配置 Cloudflare R2(推荐:出口流量免费)
<code"># 交互式配置(rclone config) # 或直接写入配置文件 mkdir -p ~/.config/rclone cat > ~/.config/rclone/rclone.conf << 'EOF' [r2] type = s3 provider = Cloudflare access_key_id = YOUR_R2_ACCESS_KEY secret_access_key = YOUR_R2_SECRET_KEY endpoint = https://YOUR_ACCOUNT_ID.r2.cloudflarestorage.com acl = private [backup-vps2] type = sftp host = 第二台VPS的IP user = root key_file = /root/.ssh/backup_key # 专用备份密钥 EOF # 测试连接 rclone ls r2: rclone ls backup-vps2:
Rclone 同步脚本
<code">cat > /usr/local/bin/backup-remote.sh << 'SCRIPT'
#!/bin/bash
set -euo pipefail
LOG="/var/log/backup-remote.log"
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a $LOG; }
# ── 同步到备用 VPS ──
log "同步备份到异地 VPS..."
rclone sync /backup/ backup-vps2:/backup/hk-vps-01/ \
--transfers 4 \
--checkers 8 \
--log-file=$LOG \
--log-level INFO
log "异地同步完成 ✓"
# ── 归档到 Cloudflare R2 ──
log "归档到 Cloudflare R2..."
# MySQL 备份:每天同步
rclone sync /backup/mysql/ r2:your-backup-bucket/mysql/ \
--transfers 4 \
--s3-chunk-size 64M \
--log-file=$LOG
# 网站文件:只同步最新的(节省存储成本)
LATEST=$(ls -dt /backup/daily/www-* | head -1)
rclone sync "$LATEST" r2:your-backup-bucket/www-latest/ \
--transfers 8
log "R2 归档完成 ✓"
SCRIPT
chmod +x /usr/local/bin/backup-remote.sh四、自动化 Crontab 调度
<code"># 编辑 crontab crontab -e # 添加以下调度规则 # ──────────────────────────────────────── # 每天凌晨 2:00 执行本地备份 0 2 * * * MYSQL_ROOT_PASSWORD="yourpassword" /usr/local/bin/backup-local.sh # 每天凌晨 3:30 执行远程同步(本地备份完成后) 30 3 * * * /usr/local/bin/backup-remote.sh # 每周日凌晨 4:00 执行完整性校验 0 4 * * 0 /usr/local/bin/backup-verify.sh # ────────────────────────────────────────
五、备份完整性验证脚本
<code">cat > /usr/local/bin/backup-verify.sh << 'SCRIPT' #!/bin/bash LOG="/var/log/backup-verify.log" ERRORS=0 log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a $LOG; } # 1. 检查本地备份目录是否存在当天备份 TODAY=$(date +%Y%m%d) if [ ! -d "/backup/daily/www-$TODAY" ]; then log "❌ 错误:当天网站备份不存在" ERRORS=$((ERRORS+1)) fi # 2. 验证 MySQL 备份文件可解压 for gz in /backup/mysql/*_${TODAY}.sql.gz; do if ! gzip -t "$gz" 2>/dev/null; then
log "❌ 错误:SQL 备份文件损坏: $gz"
ERRORS=$((ERRORS+1))
else
log "✓ SQL 备份完整: $gz"
fi
done
# 3. 检查 R2 远端文件数量
REMOTE_COUNT=$(rclone ls r2:your-backup-bucket/mysql/ | wc -l)
LOCAL_COUNT=$(ls /backup/mysql/ | wc -l)
if [ "$REMOTE_COUNT" -lt "$LOCAL_COUNT" ]; then
log "⚠️ 警告:R2 备份数量($REMOTE_COUNT)少于本地($LOCAL_COUNT)"
ERRORS=$((ERRORS+1))
fi
# 4. 发送校验报告
if [ "$ERRORS" -gt 0 ]; then
log "校验完成:发现 $ERRORS 个问题,请检查"
# 发送告警邮件(需配置 mailutils)
echo "备份校验失败,发现 $ERRORS 个问题,请立即检查 $LOG" \
| mail -s "🚨 备份告警" admin@yourdomain.com
else
log "✅ 备份校验全部通过"
fi
SCRIPT
chmod +x /usr/local/bin/backup-verify.sh六、快速恢复操作手册
从本地备份恢复网站文件
<code"># 列出可用备份 ls /backup/daily/ # 恢复到指定日期(替换现有文件) rsync -avz /backup/daily/www-20260601/ /var/www/ --delete
恢复 MySQL 数据库
<code"># 从压缩备份恢复单个数据库 gunzip < /backup/mysql/mydb_20260601.sql.gz | mysql -uroot -p mydb # 如需从 R2 下载备份 rclone copy r2:your-backup-bucket/mysql/mydb_20260601.sql.gz /tmp/ gunzip < /tmp/mydb_20260601.sql.gz | mysql -uroot -p mydb
七、存储成本估算
| 存储方案 | 月存储成本(50G数据) | 出口流量费 |
|---|---|---|
| Cloudflare R2 | $0.75($0.015/GB) | 免费 ✅ |
| AWS S3 | $1.15($0.023/GB) | $0.09/GB ❌ |
| 阿里云 OSS | ¥0.6(¥0.12/GB) | ¥0.25/GB |
推荐:Cloudflare R2 对中小规模备份最经济,无出口流量费,从 VPS 上传备份、下载恢复均不计费。
八、总结
三层备份策略(本地 rsync → 异地 VPS → Cloudflare R2)为香港 VPS 数据提供了全面保护,从日常误操作到极端的机房故障均有备案。建议所有生产环境 VPS 在上线第一天就配置好备份,而不是等到数据丢失后才后悔。