Linux rsync 增量同步怎么避免误删:--delete 预演、排除规则与回滚核对
来源:17golang原创
时间:2026-08-26 08:44:27 164浏览 收藏
凌晨备份任务结束后,目标目录里少了几份刚归档的文件,查看命令才发现同步脚本多了一行 --delete。rsync 的增量传输本身很稳,但它会把“源端没有的文件”理解成目标端应该删除;源目录写错、排除规则漏写,都会把这个判断放大。
- 首次执行带
--delete的任务,先用--dry-run只看删除清单。 - 源路径末尾斜杠决定同步“目录内容”还是“目录本身”,必须在脚本中固定写法。
- 临时文件、上传目录等业务数据用明确的
--exclude规则保护,并保存预演日志。 - 正式同步后同时核对返回码、文件数量和备份目录,异常时先停任务再回滚。
先把 rsync 的删除范围看清楚
下面用 /srv/releases/ 作为源目录,用 /srv/archive/ 作为目标目录。命令里的源路径带末尾斜杠,表示把 releases 里面的内容同步过去,而不是在 archive 下再创建一个 releases 目录。
rsync -a --delete --dry-run --itemize-changes \
/srv/releases/ /srv/archive/
--dry-run 不会写入文件,--itemize-changes 会把新增、更新和删除都列出来。输出中出现以 *deleting 开头的行时,先确认这些路径确实应该从目标端消失;只要第一行源路径就不对,后面的清单都没有参考价值。

参数设计:先做预演,再决定是否启用 --delete
源路径末尾斜杠不能凭感觉改
/srv/releases/ 同步的是目录内容,/srv/releases 则会把目录本身带到目标端。部署脚本里建议把源目录变量和目标目录变量分开写,并在运行前输出它们,避免环境变量为空时意外指向当前目录。
src='/srv/releases/'
dst='/srv/archive/'
test -d "$src" && test -d "$dst" || exit 2
printf 'source=%s target=%s\n' "$src" "$dst"
rsync -a --delete --dry-run --itemize-changes "$src" "$dst"
把删除操作变成可复核的清单
预演结果不要只在终端里看一眼。把输出写进按日期命名的日志,交接时可以明确回答“哪些文件将被删除、为什么在源端不存在”。如果删除数量明显超过平常,先停在预演阶段。
stamp=$(date +%Y%m%d-%H%M%S)
log="/var/log/rsync-preview-${stamp}.log"
rsync -a --delete --dry-run --itemize-changes \
"$src" "$dst" | tee "$log"
grep -c '^\*deleting ' "$log"
排除规则要保护业务目录,而不是掩盖误配
例如目标端的临时上传文件由另一个任务管理,就不应该被同步删除,可以显式排除;但排除规则越多,越要在日志和测试目录中单独验证。不要用一个过宽的 --exclude='*' 来“保险”,那会让预演结果失去意义。
rsync -a --delete --dry-run --itemize-changes \
--exclude='uploads/' \
--exclude='*.part' \
--exclude='runtime/' \
/srv/releases/ /srv/archive/
排除规则按相对源目录匹配。把 uploads/ 写成 /uploads/ 可以表达源目录根下的 uploads;是否需要根限定,要结合目录结构测试,不要直接复制到生产脚本。
错误处理与回滚:正式运行也要留下退路
确认预演清单后,再去掉 --dry-run。为了让被替换的文件能在短时间内找回,可以配合 --backup 和 --backup-dir,并为备份目录设置明确的保留周期。
backup="/srv/rsync-backup/$(date +%Y%m%d-%H%M%S)"
mkdir -p "$backup"
rsync -a --delete --backup --backup-dir="$backup" \
--exclude='uploads/' --exclude='*.part' \
/srv/releases/ /srv/archive/
rc=$?
test "$rc" -eq 0 || { printf 'rsync failed: %s\n' "$rc"; exit "$rc"; }
上面的备份只保护被替换或删除的目标文件,不能替代源端快照,也不能证明业务内容完整。正式任务结束后至少抽查一个新增文件、一个更新文件和一个排除目录,并记录 rsync 返回码。

常见误区与一份上线前检查表
- 把空变量当成根目录或当前目录:运行前用
test -n和test -d检查。 - 只看 rsync 的退出码:退出码正常只代表传输过程完成,还要核对删除数量与业务目录。
- 先正式执行再看差异:任何带
--delete的新任务都应先保留一次 dry-run 日志。 - 把备份目录放在同步目标里:这样下一轮同步可能再次处理备份文件,备份目录应放在独立路径。
| 检查项 | 通过标准 |
|---|---|
| 路径 | 源、目标均为预期目录,末尾斜杠含义已确认 |
| 删除清单 | dry-run 的 *deleting 路径逐项可解释 |
| 保护规则 | uploads、临时文件等目录完成独立抽查 |
| 恢复 | 备份目录可读,异常时有停止和恢复步骤 |
相关问题
不使用 --delete 能避免误删吗?
能避免“源端缺失导致目标端删除”,但目标端会保留源端已经移走的旧文件。是否启用要看目标目录是不是源端的严格镜像,不能只按命令习惯决定。
--dry-run 会创建备份文件吗?
不会。它只模拟变更并输出计划,真正的备份要在去掉该参数后执行。
发现删除清单异常时先做什么?
先停止正式任务,保存预演日志,检查源路径和排除规则,再从备份目录或源端快照核对,不要用另一条同步命令覆盖现场。
结语
rsync 的风险不在于它会删除,而在于“删除依据”通常没有被复核。把源目标路径、dry-run 清单、排除规则、备份目录和返回码固定成一条流程,--delete 才会从一次性冒险参数变成可以审计、可以回退的运维动作。
-
493 收藏
-
467 收藏
-
415 收藏
-
文章 · linux | 12小时前 | 性能优化 · Linux · 系统调用 · io_uring · 异步IO · Linux 异步IO io_uring SQPOLL IORING_SETUP_SQPOLL484 收藏
-
222 收藏
-
450 收藏
-
222 收藏
-
252 收藏
-
446 收藏
-
文章 · linux | 20小时前 | Linux · 故障排查 · auditd · 系统审计 · 日志运维 · Linux 审计日志 auditd auditctl backlog limit exceeded 队列溢出391 收藏
-
345 收藏
-
295 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习