很多人可能觉得 scp 已经够用了,但如果你经常需要在服务器之间同步文件,特别是大文件或者整个目录,那 rsync 绝对是你的不二之选。rsync,全称 remote sync,远不止是一个简单的复制工具。它的杀手锏在于其"增量传输"(delta-transfer)算法。
简单来说,当你第二次同步同一个文件时,rsync 只会传输文件中发生变化的部分,而不是整个文件。这在备份、代码部署等场景下,能极大地节省带宽和时间。
这篇文章,我们就来彻底搞懂 rsync,从基础用法到一些高级技巧,让你在日常工作中用得得心应手。
Rsync 的基本语法与核心概念
rsync 的命令结构和 scp、cp 很像,基本格式是:
rsync [选项] [源地址] [目标地址]
我们先在本地创建一些测试文件来感受一下。
# 创建两个目录
mkdir dir1 dir2
# 在 dir1 中创建 100 个空文件
touch dir1/file{1..100}
现在,我们想把 dir1 里的所有文件同步到 dir2。最常用的选项是 -a,它代表 “archive”(归档)模式,相当于多个选项的集合(-rlptgoD),可以递归同步并保留文件权限、所有者、时间戳等所有属性。
rsync -a dir1/ dir2
执行后,dir2 就会拥有和 dir1 一模一样的内容。
最重要的细节:尾部的斜杠 /
注意上面命令中 dir1/ 末尾的斜杠。这是 rsync 最容易让人迷惑,也是最关键的一个细节。
dir1/(带斜杠): 表示同步dir1目录的内容。file1到file100会被直接复制到dir2目录下。dir1(不带斜杠): 表示同步dir1这个目录本身。执行后,你会在dir2里面看到一个新建的dir1目录,文件都在dir2/dir1/下面。
这个小小的斜杠决定了完全不同的目录结构,用错的后果可能很严重。所以,我强烈建议在执行任何 rsync 命令前,都先用 --dry-run(或者缩写 -n)来模拟运行一次。
# 加上 -v (verbose) 可以看到详细的输出
rsync -anv dir1/ dir2
这个命令不会真的执行任何操作,只会打印出它计划要做的所有事情。检查输出,确认符合预期后,再去掉 -n 参数正式执行。血泪教训,请务必养成这个习惯。
远程同步:Push 与 Pull
rsync 的强大之处在于远程同步。只要你的本地机器和远程服务器配置了 SSH 免密登录,rsync 就能无缝工作。
Push:从本地推送到远程
这是最常见的场景,比如部署代码、上传备份。
# 将本地的 dir1 目录(连同目录本身)推送到远程服务器的 /home/user/backups 目录下
rsync -a ~/dir1 user@remote_host:/home/user/backups
# 将本地 dir1 目录的 *内容* 推送到远程
rsync -a ~/dir1/ user@remote_host:/home/user/backups
语法和 scp 非常相似:user@remote_host: 后面跟上远程服务器的路径。
Pull:从远程拉取到本地
反过来,把远程服务器的文件拉到本地也很简单,只需调换源和目标的位置。
# 从远程服务器拉取 /var/log 目录到本地的 ~/server_logs
rsync -a user@remote_host:/var/log ~/server_logs
常用且实用的选项组合
除了 -a 和 -n,下面这几个选项在日常工作中也极其有用。
-z(compress): 在传输过程中压缩数据。如果你的网络带宽有限,或者传输的是文本这类容易压缩的文件,这个选项能显著提升速度。-P: 这个选项是--progress和--partial的结合。--progress会显示每个文件的传输进度条,而--partial则支持断点续传。对于传输大文件或网络不稳定的情况,这哥命令简直是救星。--delete: 一个强大但危险的选项。它会删除目标目录中,源目录不存在的文件。这在做镜像备份(让目标目录和源目录完全一致)时非常有用。但请务必配合--dry-run使用,防止误删数据。
所以,一个万金油式的远程同步命令通常是这样的:
# 归档模式、显示进度、压缩、删除多余文件
rsync -azP --delete /path/to/local/source/ user@remote_host:/path/to/remote/destination/
精准控制:排除与包含
有时候我们不想同步所有文件。比如在同步一个项目代码时,我们希望排除 node_modules 目录和所有的 .log 文件。
--exclude 选项可以帮你搞定。
rsync -avz \
--exclude='node_modules' \
--exclude='*.log' \
/path/to/project/ \
user@remote_host:/path/to/deployment/
--exclude 可以使用多次,也支持通配符。如果排除规则很多,可以把它们写在一个文件里,然后使用 --exclude-from='exclude-rules.txt' 来加载。
--include 的用法稍微复杂些,它通常和 --exclude 配合使用,用来在排除的大规则中"豁免"某些文件。rsync 会按顺序匹配规则,一旦匹配成功就停止。所以 include 规则通常要放在 exclude 规则前面。
自动化你的同步任务:结合 Cron
手动的 rsync 固然好用,但真正的威力在于自动化。我们可以用 cron 来设置定时任务,比如每天凌晨自动备份网站数据。
使用 crontab -e 编辑你的定时任务,添加如下一行:
# 每天凌晨 3:00,将 /var/www/html 目录备份到远程服务器
0 3 * * * /usr/bin/rsync -a --delete /var/www/html/ user@remote_host:/backups/website/
在 cron 中使用 rsync 有几个关键点:
- 绝对路径:
cron的执行环境非常简单,可能找不到rsync命令。最好使用绝对路径(用which rsync查看)。 - SSH 免密登录: 定时任务无法输入密码,所以必须提前配置好 SSH key 认证。
- 日志记录:
cron默认会把命令的输出通过邮件发给用户。为了方便排查问题,最好将输出重定向到日志文件,比如:... > /var/log/rsync_backup.log 2>&1
那些年我们踩过的坑
最后,总结几个我个人和其他人经常遇到的问题:
- 尾部斜杠
/用错: 导致在目标位置创建了多余的目录层级。这是最常见的问题,记住:同步内容用/,同步目录本身不用。 - 权限问题: 同步后发现文件权限不对。多半是忘了用
-a选项。如果目标目录没有写入权限,rsync也会失败。 --delete误删数据: 没有先用--dry-run预览,导致目标目录的重要文件被意外删除。- 自动化脚本失败: 在
cron或脚本里,rsync找不到命令(没用绝对路径),或者卡在密码输入环节(没配置 SSH 免密)。
总的来说,rsync 是一个值得每个开发者和运维工程师投入时间去掌握的工具。一旦你理解了它最核心的几个概念——增量传输、尾部斜杠、归档模式和干跑测试——你就会发现自己再也回不去那个只会用 scp 的时代了。
关于
关注我获取更多资讯
<img src="/img/gongzhonghao.jpg" alt="公众号" class="wx-contact-img">
<div>📢 公众号</div>
<img src="/img/aixue689.jpg" alt="个人号" class="wx-contact-img">
<div>💬 个人号</div>