Linux常用命令--rsync

摘要

它做什么

rsync 把源路径的文件树同步到目标路径。只传有差异的内容(默认按大小和修改时间判断),适合备份、部署、两台机器之间对齐目录。

和常见工具的分工:

工具 适合做什么
cp / scp 整文件拷贝;scp 不增量、不方便做排除与镜像删除
curl / wget 按 URL 拉单个或一批远程资源
rsync 目录级增量同步、排除、干跑、可选删除目标多余文件

源和目标可以是本机路径,也可以是 user@host:path 形式的远程路径。经 SSH 同步时,两端都要有 rsync 可执行文件;本机只有客户端不够。

安装与确认版本

CentOS 8 一般已自带。没有时:

1
2
sudo yum install -y rsync
rsync --version

应看到类似 rsync version 3.1.3。远程主机同样执行一次 rsync --version,确认命令存在。

卸载(一般不必):

1
sudo yum remove rsync

基本语法

1
rsync [选项] 源... 目标

一次只能有一个目标。多个源会一并同步到该目标下。

本地目录同步:

1
2
3
4
5
# 把 src 目录本身同步成 dst/src(dst 下出现名为 src 的目录)
rsync -av /data/src /data/dst

# 把 src 目录里的内容同步进 dst(dst 下直接是 src 里的那些文件)
rsync -av /data/src/ /data/dst/

源路径末尾有没有 /,结果差很多:

源写法 含义
/data/src 同步这个目录(目标下会出现 src 这一层)
/data/src/ 同步这个目录里面的内容(不再多套一层 src)

目标路径末尾的 / 通常不影响“是不是目录”的判断;拿不准时先 -n 干跑看将要写入的路径。

带 --delete 做镜像时,源路径末尾 / 写错,可能把目标目录里不该删的文件删掉。正式执行前必须先 -n / --dry-run 看清单。

常用选项

短选项 长选项 作用
-a --archive 归档模式,等价于 -rlptgoD:递归,并尽量保留符号链接、权限、时间、属主属组、设备文件等。不含 ACL(-A)、xattr(-X)、硬链接(-H)
-v --verbose 列出正在处理的文件
-z --compress 传输时压缩;局域网或已压缩文件收益有限,跨公网文本类文件更有用
-n --dry-run 只演示将做什么,不改目标
-P 等价于 --partial --progress:断点保留未传完文件,并显示进度
-h --human-readable 统计数字用 KiB/MiB 等可读单位
-e --rsh=命令 指定远程 shell,常见为 ssh
--delete 删除目标上有、源上没有的文件,使目标成为源的镜像
--exclude=模式 排除匹配的路径
--exclude-from=文件 从文件读排除模式,一行一条
--bwlimit=KBPS 限制平均带宽(单位 KiB/s)
-c --checksum 用校验和判断是否相同(更慢,改时间戳但内容未变时有用)

日常备份或部署常用组合:-av 或 -avz;要看进度加 -P;要先预览加 -n。

-a 不会保留硬链接。需要硬链接时再加 -H,内存占用会升高。需要 ACL / 扩展属性时加 -A / -X,目标文件系统也要支持。

先干跑,再正式同步

1
2
3
4
5
# -n 不写入;-i 按条目打印将发生的变更类型
rsync -avn -i /data/src/ /data/backup/src/

# 确认清单无误后再去掉 -n
rsync -av /data/src/ /data/backup/src/

干跑时没有真实传数据,进度和“已传字节”统计会偏小,以文件名清单为准。

经 SSH 远程同步

默认远程 shell 就是 ssh(也可用 -e ssh 写明)。免密登录、指定端口等与普通 SSH 相同,见 Linux常用命令--ssh、scp与免密登录。

1
2
3
4
5
6
7
8
# 本机 -> 远程:把本地目录内容推到服务器
rsync -avz -P /data/app/ user@192.168.1.10:/opt/app/

# 远程 -> 本机:从服务器拉下来
rsync -avz -P user@192.168.1.10:/opt/app/ /data/app/

# SSH 非 22 端口
rsync -avz -e "ssh -p 2222" /data/app/ user@host:/opt/app/

远端路径写成 user@host:path(单个冒号)表示走远程 shell。host::module(两个冒号)是 rsync 守护进程模式,和 SSH 不是同一条通道;本文只写 SSH 场景。

推送时本机用户要能读源;拉取或写入远程时,SSH 登录用户要对远程路径有相应读/写权限。用 -a 保留属主时,目标侧通常需要足够权限(常见是 root 或具备相应 capability 的账户)。

排除与包含

1
2
3
4
5
6
7
8
9
10
11
# 排除日志和依赖目录;模式加引号,避免被本地 shell 先展开
rsync -av --exclude='*.log' --exclude='node_modules/' /data/app/ /backup/app/

# 排除规则很多时放进文件,一行一个模式
cat >/tmp/rsync-exclude.txt <<'EOF'
*.log
.git/
node_modules/
tmp/
EOF
rsync -av --exclude-from=/tmp/rsync-exclude.txt /data/app/ /backup/app/

排除的是相对“传输根”的路径模式,不是随便写本机绝对路径就生效。先 -n -v 看哪些文件仍会出现在清单里。

镜像同步:--delete

目标上多出来的文件也会被删掉,使目标与源一致:

1
2
3
4
# 务必先干跑
rsync -avn --delete /data/app/ /backup/app/

rsync -av --delete /data/app/ /backup/app/

只想删,又怕误伤时,可以分两步:先不同步删除,核对后再加 --delete;或配合 --backup / --backup-dir 把将被覆盖或删除的文件先挪到旁路目录(按需查阅 man rsync 中这两项)。

--delete 以源为权威。源写成空目录、或源路径指错,目标侧匹配到的文件可能被清空。生产目录同步前用无关测试目录练一次路径写法。

限速与大文件

1
2
3
4
5
# 平均不超过约 8192 KiB/s
rsync -avz --bwlimit=8192 /data/big/ user@host:/data/big/

# 大文件、易中断的链路:-P 保留部分文件并显示进度
rsync -avz -P /data/iso/ user@host:/data/iso/

中断后用相同命令再跑即可继续;已传完且大小、时间未变的文件会跳过。

常见任务示例

定时把网站目录备份到另一块盘(先干跑,再写进 cron):

1
rsync -av --delete --exclude='cache/' /var/www/html/ /backup/www/html/

发布代码到应用机(不删服务器上额外文件,只覆盖/新增):

1
2
3
4
rsync -avz -e ssh \
--exclude='.git/' \
--exclude='.env' \
./dist/ deploy@app01:/opt/myapp/current/

两台机器对齐同一目录(镜像):

1
rsync -avz -P --delete -e ssh /data/share/ user@host2:/data/share/

出问题先看什么

  • command not found / 远端报 rsync 不存在:在远端执行 which rsync 或 rsync --version,用 yum install rsync 装上。

  • 权限 denied:查的是 SSH 能否登录,以及登录用户对源、目标路径的读/写权限;能 ssh 登录不等于对该目录可写。

  • 传了一堆不该传的文件:检查源路径末尾 /、--exclude 是否生效;用 rsync -avn ... 看清单。

  • 目标文件被删光或少了一大片:查是否加了 --delete,以及源是否指错、是否为空。

  • 每次都全量重传:默认靠大小和 mtime;只改了内容却故意保留旧时间戳时,可临时加 -c,或修正时间同步策略。

“rsync --version 能打印”只说明本机客户端在;“同步成功”还要看退出码为 0,并用 ls / diff / 业务检查确认目标内容正确。