云服务器数据别只放一份:rsync + cron 做每日增量备份实战

举报
yd_276596855 发表于 2026/11/10 08:39:27 2026/11/10
【摘要】 一、为什么要自己做备份很多人在云服务器上跑着博客、小程序后端或者个人项目,数据库导出、上传的图片、配置文件都只放在一块系统盘上。一次误删、一次 rm 写错路径、一次系统重装,几个月的数据就没了。云厂商的快照很好用,但通常按容量计费,而且粒度粗。对个人开发者来说,用 rsync 加 cron 做一套每日增量备份,零成本、可控、恢复也快。这篇文章演示三件事:用 rsync 把关键目录增量同步到备...

一、为什么要自己做备份

很多人在云服务器上跑着博客、小程序后端或者个人项目,数据库导出、上传的图片、配置文件都只放在一块系统盘上。一次误删、一次 rm 写错路径、一次系统重装,几个月的数据就没了。云厂商的快照很好用,但通常按容量计费,而且粒度粗。对个人开发者来说,用 rsync 加 cron 做一套每日增量备份,零成本、可控、恢复也快。

这篇文章演示三件事:

  1. 用 rsync 把关键目录增量同步到备份目录;
  2. 用硬链接实现“每天一份完整快照,但只占增量空间”;
  3. 用 cron 定时执行,并自动清理过期备份。

二、rsync 基础用法

rsync 只传输变化的部分,第一次全量,之后每次只同步新增和修改的文件。最常用的参数组合:

rsync -aH --delete /srv/myapp/data/ /backup/latest/

参数说明:

  • -a:归档模式,保留权限、属主、时间戳、软链接;
  • -H:保留硬链接;
  • –delete:源端删除的文件,目标端也删除,保持一致;
  • 源路径末尾的斜杠很重要:带斜杠表示同步目录里的内容,不带斜杠表示把目录本身也放进去。

建议正式执行前先加 -n(演练模式)和 -v 看看会发生什么:

rsync -aHnv --delete /srv/myapp/data/ /backup/latest/

确认输出符合预期,再去掉 -n。

三、用硬链接做每日快照

只保留一份 latest 有个问题:如果今天误删了文件,晚上备份一跑,备份里也删了。我们需要的是“每天一份”的历史快照。

rsync 的 --link-dest 参数可以解决:对比上一天的快照,没变化的文件直接做硬链接,变化的文件才真正复制。这样每个日期目录看起来都是完整的,但磁盘只多占当天变化的那部分。

核心命令:

TODAY=(date+rsync−aH−−delete−−link−dest=/backup/snapshots/latest/srv/myapp/data//backup/snapshots/(date +%F) rsync -aH --delete --link-dest=/backup/snapshots/latest /srv/myapp/data/ /backup/snapshots/TODAY/
ln -sfn /backup/snapshots/$TODAY /backup/snapshots/latest

执行后每天会多出一个以日期命名的目录(例如 2026-11-10),latest 软链接始终指向最新一天。

用 du 可以验证空间占用:

du -sh /backup/snapshots/*

你会看到第一天占用最大,后面每天只有几 MB 到几十 MB,取决于当天的变化量。

四、把数据库也纳入备份

文件备份之外,数据库要先导出再同步。以 MySQL 为例,在备份脚本开头加一步:

mysqldump --single-transaction --routines -u backup_user myapp_db | gzip > /srv/myapp/data/db_dump_$(date +%F)_sql_gz

要点:

  • –single-transaction 对 InnoDB 表做一致性快照,不锁表;
  • 单独建一个只读权限的 backup_user,密码写在该用户主目录的 MySQL 客户端配置里,权限设为 600,不要写进脚本;
  • 导出文件放进被备份的目录,跟随 rsync 一起进快照。

五、完整备份脚本

把上面几步合成一个脚本,放在 /usr/local/bin 下,命名为 daily-backup:

#!/usr/bin/env bash
set -euo pipefail
SRC=/srv/myapp/data/
DEST=/backup/snapshots
TODAY=(date+KEEPDAYS=14mkdir−p"(date +%F) KEEP_DAYS=14 mkdir -p "DEST"

1. 导出数据库

mysqldump --single-transaction --routines -u backup_user myapp_db | gzip > /srv/myapp/data/db_dump_${TODAY}_sql_gz

2. 增量快照

if [ -d “DEST/latest"];thenrsync−aH−−delete−−link−dest="DEST/latest" ]; then rsync -aH --delete --link-dest="DEST/latest” “SRC""SRC" "DEST/TODAY/"elsersync−aH−−delete"TODAY/" else rsync -aH --delete "SRC” “DEST/DEST/TODAY/”
fi
ln -sfn “DEST/DEST/TODAY” “$DEST/latest”

3. 清理过期快照

find "DEST"−maxdepth1−typed−name"20∗"−mtime+DEST" -maxdepth 1 -type d -name "20*" -mtime +KEEP_DAYS -exec rm -rf {} +

4. 清理源目录里的旧数据库导出

find /srv/myapp/data -name “db_dump_*” -mtime +3 -delete
echo “$(date ‘+%F %T’) backup done”

记得加执行权限:

chmod +x /usr/local/bin/daily-backup

几个容易踩的坑:

  • set -euo pipefail 让任何一步失败都立即退出,避免数据库导出失败了还继续生成一份“空”快照;
  • 清理命令里的 -name “20*” 限定只删日期目录,防止误删 latest 软链接或其他目录;
  • find 删除前,可以先把 -exec rm -rf {} + 换成 -print 跑一次,确认要删的是哪些。

六、用 cron 定时执行

编辑 root 的定时任务:

crontab -e

加入一行,每天凌晨 3 点执行,并把输出追加到日志:

0 3 * * * /usr/local/bin/daily-backup >> /var/log/daily-backup_log 2>&1

cron 的环境变量很少,PATH 也很短,所以脚本里尽量写命令的完整路径,或者在 crontab 顶部加一行 PATH 定义:

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

检查是否生效:

crontab -l
grep CRON /var/log/syslog | tail

七、异地一份:同步到另一台机器

同一块盘上的备份防得住误删,防不住磁盘损坏。条件允许的话,再用 rsync 走 SSH 推到另一台机器或家里的 NAS,例如:rsync -aH --delete -e “ssh -p 22” /backup/snapshots/ 加上远端用户和主机及目标目录。

建议:

  • 用专门的密钥对,私钥只给备份用户,公钥在目标机上用 authorized_keys 的 command 限制只能执行 rsync;
  • 远端也保留多天快照,避免源端被勒索软件加密后又同步过去覆盖掉。

八、恢复演练

备份最怕的是“以为有,要用时才发现是坏的”。每个月至少做一次恢复演练:

恢复某一天的单个目录

rsync -aH /backup/snapshots/2026-11-09/uploads/ /tmp/restore-test/uploads/

恢复数据库

gunzip -c /backup/snapshots/2026-11-09/db_dump_2026-11-09_sql_gz | mysql -u root myapp_db_restore_test

确认文件数量、关键数据都对得上,才算真正有备份。

九、小结

  • rsync 负责“只传变化的部分”,–link-dest 负责“每天一份完整快照却只占增量空间”;
  • cron 负责定时,脚本里用 set -euo pipefail 保证失败即停;
  • 本机一份防误删,异地一份防盘坏,定期演练防“假备份”。

这套方案不依赖任何付费服务,十几行脚本就能让个人项目的数据安全提升一个档次。建议今天就给你的服务器配上。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。