rsync 命令详解:是什么、参数含义与同步示例
rsync 是一个文件同步命令:先比较源和目标,只传新增和变化的文件,本机复制和经 SSH 跨服务器同步都能用。最常用的写法是 rsync -avh --progress 源目录/ 目标目录/,其中 -a 是归档模式,等于 -rlptgoD,会保留权限、时间、属主和符号链接。
rsync 是 Linux 和类 Unix 系统里的文件同步工具,名字一般解释为 remote sync。它和 cp、scp 最大的不同是“先比较,再传输”:默认按文件大小和修改时间判断哪些文件变了,只传这些文件;跨网络传输时,一个大文件只改了一部分,也只传变化的数据块。所以同一条命令第一次执行是完整复制,之后再执行只补差异,中断后重新执行就能接着传。服务器之间迁移网站、定期备份目录、把安装镜像同步到各个机房,用的都是它。日常记住一个写法就够了:
rsync -avh --progress /var/www/ /data/www/
rsync 是什么:和 cp、scp 有什么区别
| 对比项 | cp | scp | rsync |
|---|---|---|---|
| 能否跨机器 | 只能本机 | 经 SSH 传到或拉自另一台机器 | 本机、经 SSH、连 rsync 守护进程(TCP 873)都可以 |
| 同一条命令再执行一次 | 全部重新复制 | 全部重新传输 | 只传新增和变化的文件 |
| 传到一半中断 | 从头再来 | 从头再来 | 重新执行即跳过已完成的文件;加 --partial 连没传完的文件也能接着传 |
| 让目标和源完全一致 | 做不到,源里删掉的文件在目标里还留着 | 做不到 | --delete 删除目标里多出来的文件 |
| 保留权限、时间、属主、符号链接 | 要加 -a |
-p 只保留时间和权限位 |
-a 一并保留 |
| 先预演再执行 | 不支持 | 不支持 | -n 只列出将要执行的操作 |
| 排除文件、限速 | 不支持 | -l 可以限速,不能排除 |
--exclude、--bwlimit |
| 依赖 | 系统自带 | 两端有 SSH 即可 | 两端都要安装 rsync |
两点容易被忽略:第一次全量复制时,rsync 不会比 scp 快多少,它的优势在第二次以后;源和目标都在本机时,rsync 不做分块比对,直接整文件复制,因为在本机把两个文件各读一遍,比直接复制还慢。另外,rsync 不能在两台远程机器之间直接同步,源和目标至少有一端在执行命令的这台机器上。
参数含义对照表
| 参数 | 全称 | 作用 | 什么时候用 |
|---|---|---|---|
-a |
--archive |
归档模式,等于 -rlptgoD |
几乎所有同步都加 |
-v |
--verbose |
列出传输的文件名,-vv 输出更多细节 |
想知道传了哪些文件 |
-z |
--compress |
传输过程中压缩 | 跨公网传代码、日志、文本;本机同步或传压缩包、图片、视频时不加 |
-h |
--human-readable |
大小显示成 K、M、G | 配合 -v、--progress |
--progress |
— | 显示每个文件的传输进度和速度 | 传大文件 |
-P |
— | 等于 --partial --progress,中断时保留已传的部分 |
跨网络传大文件 |
--info=progress2 |
— | 显示整体进度,而不是逐个文件 | 文件数量很多时(3.1 版起支持) |
--delete |
— | 删除目标中有、源中没有的文件 | 做镜像;先用 -n 预演 |
-n |
--dry-run |
只演练,不做任何修改 | 第一次执行、带 --delete 时 |
-i |
--itemize-changes |
逐个列出文件以及变化的原因 | 配合 -n 检查差异 |
-c |
--checksum |
按校验和判断文件是否相同,而不是大小和时间 | 怀疑时间戳不可靠时;要读完所有文件,很慢 |
-u |
--update |
目标里比源更新的文件不覆盖 | 防止覆盖对方的新修改 |
-e |
--rsh |
指定远程 shell,如 -e 'ssh -p 22022' |
SSH 端口不是 22 时 |
--exclude |
— | 排除匹配的文件或目录 | 跳过缓存、日志、.git |
--bwlimit |
— | 限制传输速率,默认单位 KiB/s | 白天同步,避免挤占业务带宽 |
常见组合这样读:rsync -avz 是归档、列出文件、压缩传输,适合跨网络推拉;rsync -ah --progress 是归档、大小按 K/M/G 显示、带进度,适合本机复制大文件;rsync -aHAX --numeric-ids 用于整机迁移和系统备份。
rsync -a 是什么意思:等于 -rlptgoD
| 字母 | 全称 | 保留或处理什么 |
|---|---|---|
-r |
--recursive |
递归进入子目录 |
-l |
--links |
符号链接按链接本身复制,不复制它指向的文件 |
-p |
--perms |
权限位(读、写、执行) |
-t |
--times |
修改时间;不保留的话,下次同步时所有文件都会因为时间不同被重新处理 |
-g |
--group |
属组 |
-o |
--owner |
属主,接收端以 root 运行时才生效 |
-D |
--devices --specials |
设备文件,以及命名管道、套接字等特殊文件 |
-a 不包含三项:-H(硬链接,不加的话硬链接会被复制成多个独立文件,占用成倍的空间)、-A(ACL)、-X(扩展属性,SELinux 的安全标签就存在这里)。迁移整机、备份系统目录时写成 -aHAX,再加 --numeric-ids 按原始的 UID、GID 数字保存属主,不按用户名转换,备份机上没有这些用户也不受影响,将来恢复回原系统时属主完全一致。
三类命令示例:本地、推送、拉取
远程路径的写法是 用户@主机:路径,冒号前是主机,冒号后是那台机器上的路径。写在左边的是源,右边的是目标,谁在前决定了是推送还是拉取。
本地同步
# 把网站目录复制到新挂载的数据盘,显示每个文件的进度
rsync -ah --progress /var/www/ /data/www/
# 把 /etc 备份到另一块盘上的日期目录,保留硬链接、ACL 和扩展属性
rsync -aHAX --info=progress2 /etc/ /backup/etc-$(date +%F)/
推送到远程服务器
# 把发布目录推到应用服务器,排除 .git 目录和日志文件
rsync -avz --exclude '.git/' --exclude '*.log' /opt/release/shop/ [email protected]:/opt/shop/
# 对方的 SSH 端口改成了 22022,并指定私钥
rsync -avz -e 'ssh -p 22022 -i ~/.ssh/idc_ed25519' /opt/release/shop/ [email protected]:/opt/shop/
# 白天同步 ISO 镜像目录:限速约 20 MiB/s,中断后保留已传部分
rsync -avP --bwlimit=20480 /data/iso/ [email protected]:/data/iso/
从远程服务器拉取
# 把 web01 的 Nginx 日志拉回本机
rsync -avz [email protected]:/var/log/nginx/ /srv/logs/web01/
# 远端用普通用户登录,读 /etc 需要 sudo(该用户要能免密执行 sudo rsync)
rsync -avz --rsync-path='sudo rsync' [email protected]:/etc/ /srv/backup/web01-etc/
连接 rsync 守护进程
路径写成 rsync://主机/模块/ 或 主机::模块 时,rsync 不走 SSH,而是直接连对方 TCP 873 端口上的 rsync 服务,多用于公开的软件镜像站:
rsync -av --delete rsync://mirror.example.com/rocky/9/isos/x86_64/ /data/mirror/rocky9-iso/
守护进程方式默认不加密,自己搭建时只在内网开放,不要把可写的模块暴露到公网。2025 年 1 月发布的 rsync 3.4.0 修复了多个可被远程利用的漏洞(如 CVE-2024-12084),对外提供 rsync 服务的机器要确认已经修复:自己编译安装的,看 rsync --version 第一行的版本号;用发行版软件包的,修复通常移植在原来的版本号上,以发行版的安全公告为准。
末尾斜杠的坑:差一个字符,结果完全不同
规则只看源路径:源以 / 结尾,表示“这个目录里面的内容”;不以 / 结尾,表示“这个目录本身”。目标路径末尾有没有斜杠,基本不影响结果。
| 命令 | 执行后的结果 |
|---|---|
rsync -a /var/www /data/ |
得到 /data/www/index.html,多出一层 www |
rsync -a /var/www/ /data/ |
得到 /data/index.html,www 里的内容直接铺在 /data 下 |
rsync -a /var/www/ /data/www |
得到 /data/www/index.html;/data/www 不存在时会自动创建 |
rsync -a /var/www /data/www/ |
得到 /data/www/www/index.html,常见的误操作 |
最危险的是斜杠写错又带着 --delete。本想同步到 /data/www,结果写成 rsync -a --delete /var/www/ /data/,rsync 会让整个 /data 和 /var/www 保持一致,/data 下其他目录被全部删除。带 --delete 的命令,目标路径一定写到具体的那一级目录,执行前先加 -n 看一遍。
另外两个相关细节:rsync 只会自动创建目标路径的最后一级目录,上级目录不存在时会报错,要先建好,或在 3.2.3 及以后的版本里加 --mkpath;--exclude 的匹配也和斜杠有关,--exclude 'cache/' 排除任何一层名叫 cache 的目录,--exclude '/cache/' 只排除传输根目录下的那一个,而“根目录”指的是源路径末尾斜杠所表示的那一层。
加 –delete 之前:用 -n 预演,读懂 -i 的输出
-n 加上 -i,rsync 会把将要做的每一个操作列出来,但不实际执行:
rsync -ani --delete /opt/release/shop/ [email protected]:/opt/shop/
*deleting static/old.js
.d..t...... conf/
<f.st...... conf/app.yml
<f+++++++++ static/new.js
cd+++++++++ uploads/2026/
cL+++++++++ current -> releases/v2
每行开头是 11 个字符的变化标记,后面是文件名:
| 位置 | 字符 | 含义 |
|---|---|---|
| 第 1 位 | < |
文件将发送到远端(推送时) |
| 第 1 位 | > |
文件将接收到本机(拉取或本机复制时) |
| 第 1 位 | c |
在目标端新建目录、符号链接等 |
| 第 1 位 | . |
内容不用传,只更新属性 |
| 第 1 位 | * |
附带一条消息,最常见的是 *deleting,表示将被删除 |
| 第 2 位 | f、d、L |
普通文件、目录、符号链接 |
| 第 3 到 11 位 | +++++++++ |
新建的项目 |
| 第 4、5 位 | s、t |
大小不同、修改时间不同 |
| 第 6 到 8 位 | p、o、g |
权限、属主、属组不同 |
读输出时重点看两类:*deleting 的行是不是都在预期之内;如果大量文件只显示 t(大小相同、时间不同),多半是目标当初复制时没有保留时间戳,这一轮同步会把时间对齐,之后就不会重复处理了。确认无误,去掉 -n 正式执行。
常见报错与退出码
| 报错 | 退出码 | 原因与处理 |
|---|---|---|
bash: rsync: command not found,接着是 connection unexpectedly closed (0 bytes received so far) |
127(较老版本为 12) | 远端没有安装 rsync,用 dnf install rsync 或 apt install rsync 装上 |
Permission denied (publickey,password) |
255 | SSH 本身没有连上;先用相同的端口和用户执行 ssh -p 端口 用户@主机 测通 |
send_files failed to open "…": Permission denied (13) |
23 | 发送端读不了源文件;换 root 执行,或用 --rsync-path='sudo rsync' |
chown "…" failed: Operation not permitted (1) |
23 | 目标在不允许改属主的位置,如开启了 root_squash 的 NFS、SMB/CIFS 挂载或 exFAT 盘;加 --no-owner --no-group |
file has vanished: "…" |
24 | 同步过程中源文件被删除,日志、缓存目录常见,一般可以忽略 |
中途出现 connection unexpectedly closed 或超时 |
12、30 | 网络中断或长时间无数据;加 --timeout=300 和 -P 后重新执行 |
写进脚本时,退出码 0 是完全成功,24 通常也可以视为成功,其余都要告警:
rsync -a --delete /var/www/ [email protected]:/backup/www/
rc=$?
if [ "$rc" -ne 0 ] && [ "$rc" -ne 24 ]; then
echo "rsync 失败,退出码 $rc" >&2
exit "$rc"
fi
重装、迁移之前,先把数据同步出去
在 IDC 场景里,rsync 用得最多的时刻,是服务器要重装系统、换机器或换机房之前。做法是分两轮:第一轮在业务运行时做全量同步,耗时长也不影响业务;第二轮停掉写入后再执行一次带 --delete 的同步,只补差异,停机时间就从“复制全部数据”缩短到“复制最后的改动”。
系统已经启动不了时,数据同样能救出来。客户自己就能在客户自助端把服务器切到救援模式,救援系统是临时启动的,不动硬盘上的数据,把数据分区挂载上来后,用 rsync 推到备份服务器。救援系统里如果没有 rsync,可以从备份服务器一侧用 tar 经 SSH 拉取,两端都不需要 rsync:
ssh [email protected] 'tar -C /mnt/data -cf - .' | tar -C /backup/web01 -xf -
这种方式没有增量和断点续传,中断了只能整体重来,适合数据量不大的时候应急使用。
常见问题
rsync 能做双向同步吗?
不能。rsync 每次只有一个方向,源覆盖目标;两边都会改的目录,来回执行 rsync 会让一方的修改被另一方覆盖。需要双向同步时,用 Unison、Syncthing 这类专门的工具。
Windows 上能用 rsync 吗?
Windows 没有原生的 rsync。常见做法是在 WSL 里使用 Linux 发行版自带的 rsync,以 /mnt/c/ 这样的路径访问 Windows 磁盘;也有基于 Cygwin 的 cwRsync。只是偶尔在 Windows 和 Linux 之间传文件的话,scp 或 SFTP 客户端更省事。
怎么让 rsync 定时自动执行?
先配好 SSH 密钥登录,再写进 crontab,例如每天 3 点执行:0 3 * * * flock -n /tmp/sync-www.lock rsync -a /var/www/ [email protected]:/backup/www/ >> /var/log/sync-www.log 2>&1。flock -n 保证上一轮还没跑完时,这一轮直接跳过,不会两个同步任务叠在一起。