
为什么网站需要异地定时备份
很多站长把备份当成“想起来才做一次”的任务,直到服务器磁盘故障、误删目录或被勒索脚本加密后才意识到,本地那份备份其实离受灾点太近。真正能救命的是异地且自动化的备份:数据被同步到另一台服务器,并且不依赖任何人记住执行。本文教你如何用 rsync 与 crontab 这两个 Linux 常用工具,搭出一套低成本、可验证的网站异地自动备份方案。整台服务器或数据库出问题时,你能在十几分钟内把站点恢复到迁移之前的状态,而不是从零重装。
先理解 rsync 与 crontab 的分工
rsync 负责“把文件高效地复制过去”,它只在源和目标之间传输差异部分,第一次全量、之后增量,因此对带宽(单位时间可传输的数据量)的消耗很低。crontab 则负责“按时触发同步”,把重复劳动交给系统计时器。两者组合,就是你最基本的异地容灾引擎。
这套思路比每日手动打包再上传更可靠:手动打包容易漏文件、忘记执行;而 rsync 加锁定的时间窗口,能做到“同一位的文件,每天自动出现在备份机”。下文会从密钥配置、同步命令、定时任务到数据库备份和恢复验证,一步步带你落地。
第一步:配置 SSH 密钥,让备份不再依赖密码
自动化备份的前提是命令能“免密”执行。在源服务器上生成专用密钥,把公钥拷到备份机,只允许 rsync 对应的用户访问,避免把 root 凭据暴露给每一台机器。
先在源服务器生成密钥对(若已有则跳过):
ssh-keygen -t ed25519 -C "backup-rsync" -f ~/.ssh/backup_rsync
生成的 ~/.ssh/backup_rsync.pub 就是把公钥,通过下方命令追加到备份机对应账号的 authorized_keys:
cat ~/.ssh/backup_rsync.pub | ssh backup_user@BACKUP_HOST "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
然后验证能否免密登录:ssh -i ~/.ssh/backup_rsync backup_user@BACKUP_HOST 'echo OK'。返回 OK 说明链路畅通。这里建议把源服务器对备份机的连接限制到最小权限:专门建一个 backup 用户,其 shell 只允许执行 rsync,并把 authorized_keys 加上 command="rsync --server ..." 前缀,降低被入侵后横向移动的风险。关于收紧服务器登录面的更多细节,可以参考 SSH 访问控制与审计。
第二步:写出可重复执行的同步命令
先做一次手动全量同步,确认路径、权限和返回码都正常,再交给 crontab。下面的命令把网站根目录同步到备份机,并保留文件属主与权限:
rsync -avz --delete \ -e "ssh -i /root/.ssh/backup_rsync -p 22" \ /var/www/html/ backup_user@BACKUP_HOST:/backup/site/ 2>>/var/log/backup_site.log
参数里 -a 表示归档模式(保留权限、时间戳等元数据),-z 开启传输压缩,--delete 让备份端删除源端已不存在的文件,保证两边目录一致。注意:--delete 对源路径末尾的斜杠非常敏感,/var/www/html/ 带斜杠表示“同步该目录内容”,不带斜杠则同步整个 html 目录本身。若同步的目标恰好是旧版本残留,删除动作可能误伤备份机上其他文件,务必先在测试目录演练。
把这条命令写成一个脚本文件 /usr/local/sbin/backup_site.sh 并赋予执行权限更好管理——后续要调整排除目录(例如缓存、日志、上传目录)时,只需在 rsync 里追加 --exclude 参数:
#!/bin/bash rsync -avz --delete \ --exclude="wp-content/cache/" \ -e "ssh -i /root/.ssh/backup_rsync -p 22" \ /var/www/html/ backup_user@BACKUP_HOST:/backup/site/ 2>>/var/log/backup_site.log

第三步:用 crontab 固定同步时间
脚本就绪后,编辑当前用户的定时任务:crontab -e。下面这条表示每天凌晨 3 点 10 分执行备份脚本:
10 3 * * * /usr/local/sbin/backup_site.sh
crontab 的五个时间字段依次是“分、时、日、月、星期”。10 3 * * * 即每天的 03:10。选择凌晨执行能避开业务高峰,但要注意备份机的时区和源服务器是否一致——若跨时区部署,务必用 date 确认双方时间基准。关于多机时间不同步的排查,可参考 chrony 集群时间同步指南。保存后建议先手动跑一次 bash /usr/local/sbin/backup_site.sh 确认返回码为 0,再在备份机用 ls -l --time-style=full-iso /backup/site/ 检查文件时间戳是否更新。
为避免上次任务还没跑完就触发下一次,可以在脚本开头加一行互斥锁:
flock -n /var/run/backup_site.lock /usr/local/sbin/backup_site.sh
把 cron 行改成上面的形式,flock 会保证同一时刻只允许一个实例在跑,防止大目录同步积压导致并发冲突。
第四步:把数据库纳入备份
网站文件只是站点的一半,数据库(DataBase,存储业务数据的系统)才是内容的核心。先在源服务器导出一份 SQL 快照,再随着下一轮 rsync 推到备份机。对 MySQL/MariaDB,可以用下面的脚本生成带日期命名的导出文件:
#!/bin/bash BACKUP_DIR=/backup/dbexport mkdir -p "$BACKUP_DIR" mysqldump -u backup_user -p'REDACTED' --single-transaction --routines --triggers mydb | gzip > "$BACKUP_DIR/db_$(date +%F).sql.gz"
--single-transaction 让 InnoDB 引擎在单个事务内完成导出而不锁表,适合生产环境;--routines、--triggers 保留存储过程与触发器。date +%F 生成形如 db_2026-09-15.sql.gz 的文件名,便于按天留存。为了不占满空间,建议保留最近 7 份:find "$BACKUP_DIR" -name 'db_*.sql.gz' -mtime +7 -delete。数据库变更频繁的话,还可以参考 Redis 持久化与恢复 中关于 RDB/AOF 取舍的思路,决定快照频率。
把 SQL 导出目录也加入备份机的同步范围,或者单独加一条 rsync 把 dbexport 推到备份机,就能实现“文件 + 数据库”双异地。备份机上同样要保留多份,避免数据库本身出错时把坏数据覆盖回源。

第五步:定期做恢复演练
备份的意义在于“需要时真的能用”,而这只有通过恢复演练才能确认。建议每个季度在测试机上完整恢复到最新备份:先把站点文件从备份机 rsync 拉回,再用 gunzip < db_最新.sql.gz | mysql mydb 导入数据库,最后访问前台和后台,检查页面、上传图片与插件是否正常。演练中发现的任何失败(比如某个目录漏同步、权限不对、导出的 SQL 缺表),都要回到对应步骤修正,而不是等灾难发生时才暴露。
如果你的网站流量持续增长,异地备份的容量和带宽预算也要同步扩容——可以参考 VPS(虚拟专用服务器)部署准备指南 评估备份机选型。对已经跑在正式环境里的运维人员,也可以把备份状态纳入现有监控体系,结合 TTFB 性能优化思路 一并检查备份同步对业务峰值的影响。
总结
异地自动备份并不复杂:用 ed25519 密钥打通免密通道,用一条 rsync 把网站文件增量同步到备份机,用 crontab 锁定执行时间,再用 mysqldump 把数据库快照一并推走,最后靠季度恢复演练确认整个过程真实可用。如果你需要稳定的服务器来承载这套备份链路,Hostease 提供的 [VPS](https://cn.hostease.com/vps/) 方案都支持自定义目录结构与独立磁盘空间,方便你按本文落地。
建议你从今天起按顺序做三件事:先在测试目录跑通一次 rsync 同步,再配置好 crontab 并手动验证返回码,最后约定一个固定的恢复演练日期。备份系统一旦运转起来,你在面对磁盘故障或误操作时就不再是靠运气,而是有一套可证明的兜底方案。