这个命令是干啥的
rsync 全称 remote sync,远程同步工具。你可以把它理解成 scp 的增强版。不止能拷文件,还能增量传输、断点续传、只同步差异部分。
我第一次用 rsync 是有次要往线上服务器同步一个 2GB 的压缩包。用 scp 传了 3 分钟,发现传错了目录,又得重传一遍。换成 rsync 之后,第二次传输只花了十几秒。因为它发现大部分数据已经在那里了,只传了差异的部分。
rsync 的核心原理是分块校验:把文件切成固定大小的块,计算每一块的 checksum,两端对比,只传输不一致的块。这就是"增量同步"的底层逻辑。
另一个关键特性是断点续传。你用 scp 传大文件,网络断了就得从头来过。rsync 加上 --partial 或直接用 -P 参数,下次跑就能接着上次的进度继续传。
基本用法(3分钟上手)
最常用的组合是 rsync -avz:
# 把本地目录同步到远程服务器
rsync -avz ./project/ user@server:/var/www/
解释一下这几个参数:
- ·
-a:归档模式,保留权限、时间戳、软链接、递归子目录等(等于 -rlptgoD) - ·
-v:verbose,输出详细传输过程 - ·
-z:传输时压缩,减少网络数据量
本地同步,两台机器之间没有网络也照样用:
# 把 /data/backup 同步到 /mnt/disk/backup
rsync -av /data/backup/ /mnt/disk/backup/
注意尾部斜杠的区别:
# 带斜杠:同步目录内容
rsync -av src/ dst/ # dst 里会有 src 下的文件
# 不带斜杠:同步目录本身
rsync -av src dst/ # dst 里会有 src 目录
这个坑我踩了不下三次。你要同步 src/ 文件夹里的文件到 dst/,那 src 后面一定要加斜杠。不然 rsync 会在 dst 下面再创建一层 src 目录。
断点续传(--partial / -P):
# -P 等于 --partial --progress,显示进度并支持续传
rsync -avP bigfile.tar.gz user@server:/tmp/
进阶骚操作
--delete:同步删除
这是 rsync 最猛的功能之一。你把本地某些文件删了,想把远程也同步删掉?
# 让远程完全和本地保持一致,删除远程多出来的文件
rsync -av --delete ./site/ root@server:/var/www/html/
这招好用到飞起,但也危险。你本地误删了一个文件,跑完这条命令,远程也就删了。建议先加 --dry-run 模拟跑一遍。
# 先看看会删掉哪些文件,不实际执行
rsync -av --delete --dry-run ./site/ root@server:/var/www/html/
--exclude:排除文件
有些目录你不想同步,比如 node_modules、.git、缓存目录:
# 排除 node_modules 和 .git 目录
rsync -av --exclude='node_modules' --exclude='.git' ./site/ root@server:/var/www/html/
也可以用 --exclude-from 把规则写进文件:
# 创建一个排除规则文件
echo "node_modules" > exclude.txt
echo ".git" >> exclude.txt
echo "*.log" >> exclude.txt
# 引用规则文件排除
rsync -av --exclude-from=exclude.txt ./site/ root@server:/var/www/html/
--bwlimit:限速
公司带宽本来就不够用,rsync 跑起来能把你整个网络吃掉。这就用到限速了:
# 限制带宽为 1MB/s(单位是 KB/s,1024 = 1MB)
rsync -av --bwlimit=1024 bigfile.tar.gz user@server:/tmp/
实测:不限速,scp 能把上行带宽跑满,SSH 都卡。限速到 512KB/s 之后,同事刷网页就不骂娘了。
远程同步的核心参数搭配
我的常用组合:
# 生产环境同步模板
rsync -avz --progress --partial --delete --bwlimit=2048 \
--exclude='*.cache' --exclude='logs/' \
./dist/ deploy@prod-server:/app/current/
加了 --progress 能看到每个文件的传输百分比和速度。
rsync over SSH(自定义端口)
rsync 默认走 SSH 协议,改了端口怎么搞?
# 远程端口是 2222,用 -e 指定 SSH 参数
rsync -avz -e 'ssh -p 2222' ./data/ user@server:/backup/
避坑指南
1. 尾部斜杠决定生死
再说一次:
rsync -av /src /dst # 结果是 /dst/src/...
rsync -av /src/ /dst # 结果是 /dst/...
差一个斜杠,目录结构就多一层。
2. 同步大文件记得检查磁盘空间
rsync 默认会在目标目录生成临时文件(.文件名.随机字符串),同步完成后再重命名。如果你的磁盘就剩 2GB,要同步一个 1.5GB 的文件,临时文件也会占 1.5GB,直接就满盘了。
解决办法:
# 告诉 rsync 直接用目标文件,不要临时文件
rsync -av --inplace bigfile.tar.gz user@server:/tmp/
--inplace 直接在目标文件上原地覆盖,省掉那一次额外的临时存储。但注意:如果同步过程中断了,目标文件是损坏的,必须重新同步。
3. rsync 和 scp 怎么选
| 场景 | 推荐 |
|---|
| 传一次性的小文件 | scp 简单 |
| 反复同步同一批文件 | rsync |
| 大文件+可能断网 | rsync -P |
| 需要删除远程多余文件 | rsync --delete |
| 远程目录结构一样 | scp -r 也行,但不增量 |
一句话:日常拷文件用 scp,做同步用 rsync。
4. ssh 免密配合 rsync
rsync 走 SSH,每次都输密码太烦。配好 SSH key:
# 本地生成密钥
ssh-keygen -t ed25519
# 把公钥传到服务器
ssh-copy-id user@server
之后 rsync 就不用输密码了,配合 cron 可以实现定时同步。
实战场景(重点!结合真实运维场景)
场景一:网站部署自动化
我管理的一个前端项目,每次发版都要把构建产物同步到生产服务器。
#!/bin/bash
# 本地构建
npm run build
# 同步到测试服务器(先模拟看看会不会删错东西)
rsync -avz --delete --dry-run --exclude='*.map' ./dist/ test-server:/var/www/app/
echo "确认无误后,去掉 --dry-run 执行正式同步"
实际跑的时候,去掉 --dry-run 就行。配合 CI/CD 流程,每次 git push 自动触发构建和 rsync。
场景二:日志每天增量备份
生产服务器的日志每天增长,全量拷贝浪费带宽和时间:
# 每天凌晨 2 点,增量备份日志到备份机
rsync -avz --partial --bwlimit=512 \
/var/log/app/ backup-server:/backup/logs/$(date +%Y%m%d)/
配合 crontab:
# crontab -e
0 2 * * * /usr/bin/rsync -avz --partial /var/log/app/ backup-server:/backup/logs/
场景三:跨机房数据迁移
我需要把一个 500GB 的数据从北京机房同步到上海机房,网络条件一般:
# 第一步:全量同步(后台跑,不占用终端)
nohup rsync -avzP --bwlimit=10240 --partial \
/data/ user@shanghai:/data/ \
> /tmp/rsync_full.log 2>&1 &
第一次全量可能跑几个小时。之后每 15 分钟增量同步一次:
# 增量同步,只传新增或修改的文件
rsync -avz --delete --bwlimit=10240 \
/data/ user@shanghai:/data/
增量同步通常几十秒到几分钟,因为只传变化的数据。
场景四:本地磁盘备份
把重要数据从 SSD 同步到外接硬盘:
# USB 硬盘挂载到 /mnt/usb
rsync -av --delete --info=progress2 \
/home/user/important/ /mnt/usb/backup/important/
--info=progress2 能显示整体进度(跟 -P 每个文件的进度不同)。
今日作业(一道小题目)
题目:你用 rsync 实现一个"自动增量备份脚本"。
要求:
1. 把 /home/user/data/ 同步到 /backup/data/
2. 排除所有 .tmp 文件和 cache/ 目录
3. 保留文件权限和时间戳
4. 同步时限速 1MB/s
5. 首次运行前,先用 dry-run 检查会同步哪些文件
6. 把同步日志写到 /var/log/backup.log
写完后把你的命令贴在评论区,看看和别人有什么不同。