rsync 增量同步实战:常用参数、排除规则与远程同步
同步一个几个 G 的目录到服务器,哪怕只改了几个文件,用 scp 或 cp 还是得把整个目录重新传一遍——网络稍微差一点,等待时间就长得离谱。rsync 解决的正是这个问题:只传输真正变化的部分,其余的原样跳过。
这是 Linux 命令系列的一篇,承接 Linux 常见命令与工具地图。
rsync 为什么”增量”
rsync 判断”变了没”,不是简单看文件名或者改动时间——它用的是一套块级别的对比算法(由 Andrew Tridgell 提出,通常直接叫 rsync algorithm):把文件切成一个个数据块,两边同时计算校验和,只有校验和对不上的块才会真正传输,没变的块直接跳过不传。
这意味着即使是同一个文件,哪怕只改了中间一小段,rsync 也只传那一小段变化的数据,不会把整个文件重传一遍。目录同步同理:目录里没变的文件直接跳过,只有新增、删除、内容变化的文件才会被处理。这是它比 cp/scp 快的根本原因,不是”压缩得更好”这类表面优化。
最常用的参数组合:-avz
日常用 rsync 基本都是这个组合起手:
1 | rsync -avz ./local_dir/ user@host:/remote/path/ |
-a 是这几个参数里最关键的一个:不加 -a 的话,rsync 默认不会递归进子目录,也不会保留权限和时间戳这些元信息,同步出来的结果跟预期会差很多。
-P:进度条和断点续传
同步大文件的时候,光有 -avz 还不够——看不到进度,网络一断就得从头再来:
1 | rsync -avzP bigfile.iso user@host:/remote/path/ |
-P 对大文件、不稳定的网络环境特别有用——没有 --partial 的话,传到一半中断,之前传的部分会被删掉,下次又得从零开始。
–delete:让目标和源完全一致
前面的同步只会”新增/更新”文件,源目录里删掉的文件不会影响目标目录——目标那边的旧文件会一直留着。想让目标和源保持完全一致(源删了,目标也跟着删),要加 --delete:
1 | rsync -avz --delete ./local_dir/ user@host:/remote/path/ |
--delete 属于”威力大但容易出事”的参数,用之前一定要先确认源和目标的方向没搞反。
–dry-run:先演练一遍,别直接动手
尤其是带了 --delete 这种会删除文件的操作,实际执行前应该先跑一遍演练模式,只看会发生什么,不真的执行:
1 | rsync -avz --delete --dry-run ./local_dir/ user@host:/remote/path/ |
只要命令里带了 --delete,先 --dry-run 看一眼输出,是能避免”手滑删错文件”最简单也最有效的办法。
排除规则:跳过不想同步的文件
项目目录里的 .git、node_modules 这类文件,同步时通常不需要带上:
1 | rsync -avz --exclude='.git' --exclude='node_modules' ./project/ user@host:/remote/project/ |
远程同步和一个经典的坑:源目录带不带末尾斜杠
rsync 同步远程主机走的是 SSH 通道,语法跟 scp 类似但功能强得多:
1 | rsync -avz ./local_dir/ user@host:/remote/path/ |
源目录路径末尾带不带 /,行为是不一样的——这是 rsync 最容易踩的坑,官方手册专门用例子说明过:
1 | rsync -av /src/foo /dest |
简单记忆:源路径末尾的 / 决定”要不要在目标里多包一层目录”——同步目录内容用 foo/,同步目录本身(连同目录名)用 foo(不带斜杠),目标那边对应地要不要手动加上这层目录名。搞混这个经常导致同步出来的目录结构和预期差一层,排查起来莫名其妙。
写到这里
rsync 的核心就是这几件事:增量传输省时间、-P 应付大文件和不稳定网络、--delete 配 --dry-run 保证安全、--exclude 跳过不需要的内容。这几个参数组合起来,日常的目录同步和轻量级备份基本够用——更复杂的定时增量备份场景,通常是在这套参数基础上配合 cron 或者专门的备份工具,但底层同步逻辑还是这些。






