首页 > Sysadmin > 正文

Linux 用 rsync 同步目录:斜杠、删除与断点续传

huyuanwen 2026-10-29 Sysadmin

源路径带不带尾斜杠决定目录层级;rsync 默认只比 mtime 和大小,漏改要换 -c;断点续传靠 –partial。三大坑均经 WSL2 实测。

一、尾斜杠决定目录层级:先记两条等价写法

rsync -a /data/src /backup/            # 结果是 /backup/src/...,多一层 src
rsync -a /data/src/ /backup/           # 结果是 /backup/...,只拷内容
rsync -a /data/src/ /backup/src        # 与上一条落点完全相同(实测等价)

实测同一份 src(含两个子目录):不带斜杠时目标树是 d1/src/a.txt;带斜杠时是 d2/a.txt,目录本身没有被搬过去。手册的说法:把源路径的尾 / 理解为”拷这个目录的内容”,不带就是”把这个目录拷过去”;并给出与实测一致的等价对 rsync -av /src/foo /dest 与 rsync -av /src/foo/ /dest/foo [1]。配套规律:目标路径带不带斜杠不影响结果(实测 d2 与 d2/ 落点相同);只有源路径的斜杠改变层级。首次创建目标目录时 rsync 会自己建(实测 created directory 提示)。

二、–delete 的安全预览:先 -ain,再动手

rsync -ain --delete /data/src/ /backup/   # 预览:只打印,不落盘
rsync -ai  --delete /data/src/ /backup/   # 确认无误后再去掉 n 实跑

手册对 –dry-run 的原话:做一次不落盘的试跑,常与 -v、-i 组合,用来在真跑之前看清 rsync 将要做什么;并且承诺 -i 的逐行输出在试跑与实跑之间应当完全一致 [1]。实测印证:预览里 *deleting sub2/old.log,实跑删除的正是同一行。–delete 家族还有 –delete-before / –delete-during / –delete-delay / –delete-after 四个时机变体,Debian 手册明确 rsync 3.0.0 起 –delete 默认就是 –delete-during [2]。两个实测护栏:–max-delete=2 时删到第 2 个就停,报 Deletions stopped due to --max-delete limit、错误码 25;预览里的删除行以 *deleting 开头,扫一眼这一列就能预判会被删什么。

三、排除规则:–exclude 与 –filter 的锚点差别

rsync -a --exclude='*.log' /data/src/ /backup/          # 任意层级的 .log 都排除
rsync -a --filter='-p /sub2/' /data/src/ /backup/       # 只排除顶层 sub2/(实测)
rsync -a --exclude-from=/etc/rsync.ignore /data/src/ /backup/  # 规则写文件里

手册的 FILTER RULES:模式前加锚 / 就锚定到 transfer 起点而不是末端,例如 /foo/** 只匹配 transfer 根下的 foo [1]。实测 --filter='-p /sub2/' 后目标里 sub1 正常同步、sub2 整个消失,而上一节不带锚的写法会把各层同名目录一起排掉。-p 表示该规则同时作用于推送方向 [2]。规则多时用 –exclude-from 指一个规则文件,便于版本管理与复用。

四、rsync 凭什么判断”文件没变”:默认 mtime+大小

rsync 的默认比对是 mtime 加文件大小,不是内容。实测构造了一个”内容已改、大小相同、mtime 被 touch 成一样”的文件:默认 rsync -ai 一行输出都没有(判定无需传输);换成 rsync -aic 立刻传输,itemize 行写作 >fc........,c 标记传输方式已换成校验和 [1]。所以从备份介质恢复、解压保留原时间戳的归档之后,补一次 -c 才可靠。手册还给出 –modify-window=NUM(-@):两个时间戳差值不超过 NUM 即视为相等,默认 0;推荐对 FAT/exFAT 设 1,因为 FAT 的时间只有 2 秒分辨率 [2]。本地对拷时 rsync 默认走 whole-file(-W)而不算增量,手册明确”源与目标都是本地路径时默认如此” [1],跨机器才轮到 delta 算法加 -z 压缩(文档口径,未实测)。

五、大文件断了怎么续传:–partial 实测对比

rsync -a --partial --bwlimit=2000 /data/big.bin /backup/   # 中断后保留半截文件
rsync -a --partial-dir=.rsync-partial /data/big.bin /backup/  # 半截放临时目录

实测 120MB 文件限速传输、3 秒后 SIGTERM 杀掉:默认行为下退出码 20(手册退出码表:20 = 收到中断信号 [1]),目标目录里半截文件被删、重跑从 0 开始;加 –partial 后 6193152 字节的半截留在原地,重跑 itemize 显示 >f.st......——只补差异段后完成。手册对 –partial 的解释:告诉 rsync 保留部分传输的文件,让后续传输快得多;–partial-dir 则把半截文件放进指定目录、续传用完自动删除,且与 –partial、–delay-updates 互斥 [2]。注意 –partial-dir 的官方提醒:本地拷贝默认 whole-file 时,找到的 partial-dir 文件会被直接移除(文档口径);实测续传确实以完整传输收尾。限速用 –bwlimit,单位 KB/s(手册口径),cron 白天的备份任务建议配上,避免抢生产带宽。

六、出错怎么读:退出码与排错速查

rsync 失败时先看退出码再翻日志。手册的 EXIT VALUES 表:0 成功、1 语法或用法错误、23 部分源/目标缺失、24 部分传输文件消失、25 被 –max-delete 拦停、10/11/12 套接字/文件/协议流 I/O 错误、20 收到中断信号 [1]。实测:源目录不存在退出码 23;未知选项退出码 1;SIGTERM 中断退出码 20;–max-delete 拦停报错误码 25。

| 现象 | 原因 | 处理 | | — | — | — | | 目标里多出一层同名目录 | 源路径没带尾斜杠 | 源加 / 或目标补上目录名(实测) | | 文件明明变了却没同步 | mtime 与大小都没变 | 补一次 -c 校验和比对(实测) | | 半截文件消失、白传了 | 默认中断即删 | 加 –partial 或 –partial-dir(实测) | | 目标文件属主变成执行用户 | 非 root 无权 chown | 用 root 跑,或 –chown 映射(实测) | | –delete 不敢下手 | 怕误删 | 先 -ain 预览,再配 –max-delete(实测) | | 大目录首扫慢、内存高 | 递归扫描全量建列表 | 试 –no-inc-recursive 对比(文档口径) |

**常见提问**

  • 源目录带不带斜杠到底差在哪?不带是”把目录本身拷过去”,带是”只拷目录内容”,手册与实测一致:/src/foo → /dest 与 /src/foo/ → /dest/foo 结果相同 [1]。
  • 为什么文件改了 rsync 却不传?默认只看 mtime 加大小,两者都没变就跳过;实测 -c 能抓住这种文件,代价是两端都要算校验和,大目录会慢(实测)。
  • –delete 会不会把目标清空?它只清理”传输目录范围内”目标多出来的文件;安全流程是 -ain 预览加 –max-delete 兜底,实测超限即停并报 25。
  • 跨机器同步两端都要装 rsync 吗?手册 SETUP 章节要求远程传输两端都有 rsync(文档口径,本机未搭远程环境实测);只有一端可用时退回 scp。
  • 普通用户跑会不会保留 root 属主?不会。实测 nobody 执行后目标文件属主是 nobody;保留属主要 root 跑,或用 –chown / –usermap 显式映射(实测)。
  • 局限性:全部实测在 WSL2 的 Ubuntu 24.04(rsync 3.2.7)完成;远程 SSH 传输、–partial-dir 在 delta 模式下的续传效果、-z 与 –whole-file 的跨机性能差异、–no-inc-recursive 的大目录表现均为文档口径,未在本机复现;RPM 系发行版未测。

    **实测记录**

  • 测试机:WSL2 Ubuntu 24.04 LTS、内核 6.6.114.1-microsoft-standard-WSL2;rsync 3.2.7(协议 31,系统自带,未安装任何新包);2026-10-29 以 root 执行,测试目录 /tmp/rt 已删除。
  • 尾斜杠:不带斜杠落 d1/src/...,带斜杠落 d2/...;目标带不带斜杠结果相同。
  • 删除与预览:-ain –delete -i 预览 *deleting sub2/old.log 与实跑逐行一致;–max-delete=2 删 2 停 1,报错误码 25。
  • 排除:–filter=’-p /sub2/’ 后目标无 sub2,sub1 正常。
  • 比对:同大小同 mtime、内容不同的文件,默认 -ai 无输出,-aic 传输并显 >fc........。
  • 续传:120MB 传输中途 SIGTERM,退出码 20;默认半截被删重传,–partial 保留 6193152 字节且重跑显 >f.st...... 完成;–partial-dir 半截进 .rsync-partial,本地 whole-file 默认下续传为完整传输。
  • 权限:nobody 执行后目标属主 nobody、权限 644;root 加 –chown=daemon:daemon 后属主属组均为 daemon。
  • 退出码:源缺失 23、未知选项 1、中断 20、max-delete 25。
  • 未实测:远程 SSH 传输、RPM 系发行版、-z 压缩效果。

  • 参考资料

    文中主要命令已在 WSL Ubuntu(24.04)实测并核对其在 Debian 系与通用发行版的文档口径。