数据丢失可能由硬件故障、误操作、安全入侵等多种原因导致。一套可靠的自动备份方案是VPS运维的底线。本文提供一个完整的VPS备份解决方案,包括网站文件、数据库、配置文件的备份,以及定时执行和异地同步。
Tip: 备份的核心原则:3-2-1策略——至少3份备份,存储在2种不同介质上,其中1份在异地。
VPS上需要备份的关键数据:
cat > /usr/local/bin/vps-backup.sh << 'SCRIPT'
#!/bin/bash
#================================================
# VPS全量备份脚本
# 备份内容:网站文件 + 数据库 + 配置文件
#================================================
# 配置区域
BACKUP_DIR="/backup"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_PATH="${BACKUP_DIR}/${DATE}"
LOG_FILE="/var/log/vps-backup.log"
RETENTION_DAYS=7
# 数据库配置(使用~/.my.cnf中的凭据)
DATABASES="myapp_db wordpress_db"
# 远程备份配置
REMOTE_ENABLED=true
REMOTE_USER="backup"
REMOTE_HOST="backup-server.example.com"
REMOTE_PORT="22"
REMOTE_DIR="/backup/bwg-vps"
#------------------------------------------------
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> $LOG_FILE
}
log "========== 开始备份 =========="
mkdir -p $BACKUP_PATH
# 1. 备份网站文件
log "备份网站文件..."
tar czf ${BACKUP_PATH}/www_${DATE}.tar.gz /var/www/ 2>/dev/null
if [ $? -eq 0 ]; then
log "网站文件备份成功: $(du -h ${BACKUP_PATH}/www_${DATE}.tar.gz | cut -f1)"
else
log "网站文件备份失败!"
fi
# 2. 备份数据库
log "备份数据库..."
for DB in $DATABASES; do
mysqldump --single-transaction --routines --triggers \
$DB 2>>$LOG_FILE | gzip > ${BACKUP_PATH}/${DB}_${DATE}.sql.gz
if [ $? -eq 0 ]; then
log "$DB 备份成功: $(du -h ${BACKUP_PATH}/${DB}_${DATE}.sql.gz | cut -f1)"
else
log "$DB 备份失败!"
fi
done
# 3. 备份配置文件
log "备份配置文件..."
tar czf ${BACKUP_PATH}/configs_${DATE}.tar.gz \
/etc/nginx/ \
/etc/php/ \
/etc/mysql/ \
/etc/letsencrypt/ \
/etc/fail2ban/ \
/etc/sysctl.d/ \
/etc/ssh/sshd_config \
2>/dev/null
log "配置文件备份完成"
# 4. 备份crontab
crontab -l > ${BACKUP_PATH}/crontab_${DATE}.txt 2>/dev/null
log "Crontab备份完成"
# 5. 创建归档
log "创建归档..."
cd $BACKUP_DIR
tar czf ${DATE}.tar.gz ${DATE}/
rm -rf ${BACKUP_PATH}
log "归档完成: $(du -h ${BACKUP_DIR}/${DATE}.tar.gz | cut -f1)"
# 6. 远程同步
if [ "$REMOTE_ENABLED" = true ]; then
log "开始远程同步..."
rsync -avz -e "ssh -p ${REMOTE_PORT}" \
${BACKUP_DIR}/${DATE}.tar.gz \
${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DIR}/ 2>>$LOG_FILE
if [ $? -eq 0 ]; then
log "远程同步成功"
else
log "远程同步失败!"
fi
fi
# 7. 清理过期备份
log "清理${RETENTION_DAYS}天前的备份..."
find $BACKUP_DIR -name "*.tar.gz" -mtime +$RETENTION_DAYS -delete
log "清理完成"
# 统计
TOTAL_SIZE=$(du -sh $BACKUP_DIR | cut -f1)
log "备份总大小: $TOTAL_SIZE"
log "========== 备份结束 =========="
SCRIPT
chmod +x /usr/local/bin/vps-backup.sh
# 编辑定时任务
crontab -e
# 每天凌晨3点执行备份
0 3 * * * /usr/local/bin/vps-backup.sh
# 每12小时备份一次(高更新频率站点)
0 3,15 * * * /usr/local/bin/vps-backup.sh
# 查看定时任务
crontab -l
rsync是最高效的远程同步工具,支持增量传输,只同步变化的部分:
# 基本用法:同步到远程服务器
rsync -avz /backup/ user@remote:/backup/bwg/
# 使用SSH指定端口
rsync -avz -e "ssh -p 2222" /backup/ user@remote:/backup/bwg/
# 删除远程已不存在的文件(镜像同步)
rsync -avz --delete /backup/ user@remote:/backup/bwg/
# 限制带宽(KB/s),避免影响正常业务
rsync -avz --bwlimit=5000 /backup/ user@remote:/backup/bwg/
# 排除不需要同步的文件
rsync -avz --exclude='*.log' --exclude='cache/' /var/www/ user@remote:/backup/www/
远程服务器需要配置SSH密钥免密登录,详见SSH密钥教程。
合理的保留策略可以在空间和安全之间取得平衡:
# 简单策略:保留最近N天
find /backup -name "*.tar.gz" -mtime +7 -delete
# 进阶策略:保留每日7天 + 每周4周 + 每月6月
# 创建保留策略脚本
cat > /usr/local/bin/backup-retention.sh << 'SCRIPT'
#!/bin/bash
BACKUP_DIR="/backup"
# 保留最近7天的每日备份
# (默认不删除)
# 7天前到30天前的备份,只保留每周日的
find $BACKUP_DIR -name "*.tar.gz" -mtime +7 -mtime -30 | while read file; do
DOW=$(date -r "$file" +%u) # 获取星期几
if [ "$DOW" != "7" ]; then # 不是周日就删除
rm "$file"
fi
done
# 30天前的备份,只保留每月1号的
find $BACKUP_DIR -name "*.tar.gz" -mtime +30 | while read file; do
DOM=$(date -r "$file" +%d) # 获取日期
if [ "$DOM" != "01" ]; then # 不是1号就删除
rm "$file"
fi
done
# 180天前的备份全部删除
find $BACKUP_DIR -name "*.tar.gz" -mtime +180 -delete
SCRIPT
chmod +x /usr/local/bin/backup-retention.sh
搬瓦工KiwiVM面板提供了Snapshots功能,可以对整个VPS创建系统级快照:
KiwiVM快照是VPS级别的完整备份,但有数量限制且不支持自动化。建议同时使用脚本备份和KiwiVM快照。
定期验证备份可以正常恢复:
# 解压备份归档
cd /tmp
tar xzf /backup/20260328_030000.tar.gz
# 验证网站文件
tar tzf 20260328_030000/www_20260328_030000.tar.gz | head
# 验证数据库备份
gunzip -t 20260328_030000/myapp_db_20260328_030000.sql.gz
# 恢复到测试数据库验证
mysql -u root -p -e "CREATE DATABASE test_restore;"
gunzip < 20260328_030000/myapp_db_20260328_030000.sql.gz | mysql -u root -p test_restore
mysql -u root -p -e "DROP DATABASE test_restore;"
# 清理测试文件
rm -rf /tmp/20260328_030000/
# 查看最近的备份日志
tail -50 /var/log/vps-backup.log
# 检查备份文件是否正常生成
ls -lh /backup/*.tar.gz
# 检查磁盘空间
df -h /backup
# 简单的备份监控(加入crontab,备份失败时告警)
# 检查今天是否有新备份
TODAY=$(date +%Y%m%d)
if ! ls /backup/${TODAY}*.tar.gz 1>/dev/null 2>&1; then
echo "今日备份缺失!" | mail -s "VPS备份告警" admin@example.com
fi
数据库备份的详细方案请参考MySQL数据库备份教程。
Tip: 更多教程请查看新手教程。