服务器再稳定也可能翻车:误删数据、被入侵、磁盘损坏、升级失败。没有备份等于把所有筹码压在运气上。自动备份不复杂,核心就三件事:备份什么、什么时候备份、备份放哪里。
备份策略对比
| 策略 | 频率 | 保留 |
|---|---|---|
| 全量备份 | 每周一次 | 保留 4 周 |
| 增量备份 | 每天一次 | 保留 7 天 |
| 实时同步 | 持续 | 按需回滚 |
备份内容
一个典型 Web 服务器上需要备份的东西:
- 数据库:MySQL/MariaDB、PostgreSQL 等
- 网站文件:/var/www/html 或你的站点目录
- 配置文件:Nginx、Apache、PHP-FPM、SSH 等配置
- 用户数据:上传的附件、日志等
编写备份脚本
下面是一个通用的 Linux VPS 备份脚本:
#!/bin/bash
# /opt/backup/backup.sh
BACKUP_DIR="/backup"
DATE=$(date +%Y%m%d)
RETAIN_DAYS=30
# 创建目录
mkdir -p "$BACKUP_DIR"
# 备份 MySQL
mysqldump -u root -p'你的密码' --all-databases --single-transaction > "$BACKUP_DIR/db_all_$DATE.sql"
# 备份网站文件和配置
tar czf "$BACKUP_DIR/www_$DATE.tar.gz" /var/www/ /etc/nginx/ /etc/ssh/sshd_config
# 压缩数据库
xz "$BACKUP_DIR/db_all_$DATE.sql"
# 清理旧备份
find "$BACKUP_DIR" -name "db_all_*.sql.xz" -mtime +$RETAIN_DAYS -delete
find "$BACKUP_DIR" -name "www_*.tar.gz" -mtime +$RETAIN_DAYS -delete
echo "Backup completed: $DATE"
设置定时任务
把脚本加到 crontab,每天凌晨 3 点执行:
0 3 * * * /opt/backup/backup.sh >> /var/log/backup.log 2>&1
注意:不要把数据库密码直接写在脚本里,可以用 mysql 的配置文件 ~/.my.cnf:
[mysqldump]
user=root
password=你的密码
然后设置权限 chmod 600 ~/.my.cnf。
异地备份
本地备份没意义——服务器挂了备份也没了。常见方案:
# rsync 到另一台服务器
rsync -az --delete /backup/ user@backup-server:/backups/vps1/
# 同步到对象存储
aws s3 sync /backup/ s3://your-bucket/vps1/ --delete
# 或者用 rclone 支持多种云存储
rclone sync /backup/ remote:backup-bucket/vps1/
验证备份
没验证过的备份等于没有备份。定期做恢复测试:
# 解压并测试导入
xz -d db_all_20260806.sql.xz
mysql -u root -p -e "CREATE DATABASE test_restore;"
mysql -u root -p test_restore < db_all_20260806.sql
测试恢复成功后,删除 test_restore 数据库。
备份策略建议
| 数据类型 | 频率 | 保留周期 |
|---|---|---|
| 数据库 | 每日 | 30 天 |
| 网站文件 | 每日或每周 | 14 天 |
| 配置文件 | 每次修改后备份 | 长期保留 |
| 完整系统镜像 | 每月 | 3 个月 |
更多服务器运维教程,请访问 fenij.com。
常见问题
问:备份文件太大怎么办?
答:用增量备份(rsync --link-dest)或只备份变化的数据库 binlog。大文件还可以用对象存储的生命周期策略自动转冷存。
问:mysqldump 会锁表吗?
答:加 --single-transaction 参数可以在 InnoDB 表上做一致性导出而不锁表。MyISAM 表仍然会锁。
问:备份脚本放在哪里安全?
答:脚本本身可以放在 /opt/backup/,但密码不要写在里面。备份目录不要放在 web 可访问路径下,避免被下载。