rsync (remote sync) 是一款功能强大的文件同步和传输工具,广泛应用于 Linux/Unix 系统中。它以其高效的增量同步算法而闻名,该算法只传输源文件和目标文件中存在差异的部分,从而大大减少了网络带宽的消耗和数据传输时间。
这对于备份、镜像和服务器之间的数据迁移等场景至关重要。
rsync 的核心优势
- 增量同步:只传输文件的差异部分,速度极快。
- 保持属性:可以保持文件的权限、时间戳、所有者和组信息。
- 安全传输:可以配合 SSH,使用加密通道进行安全的数据传输。
- 功能丰富:支持排除、包含特定文件/目录,支持删除目标端多余文件等。
基本语法
rsync 的基本命令格式如下:
Bash
rsync [options] SRC... [DEST]
[options]: 选项,例如 -a, -v, -z 等。
SRC: 源目录或文件。
DEST: 目标目录或文件。
SRC 和 DEST 可以是本地路径,也可以是远程路径。远程路径的格式为 [user@]host:path。
最常用和最重要的选项组合 -avz
在绝大多数场景下,我们都会使用 -avz 这个组合,它非常实用且高效。
Bash
rsync -avz [SRC] [DEST]
-a, --archive:归档模式,表示以递归方式传输文件,并保持所有文件属性。它等同于 -rlptgoD 的组合。
-r:递归复制目录。
-l:复制符号链接本身,而不是链接所指向的文件。
-p:保持文件权限。
-t:保持文件修改时间。
-g:保持文件所属组。
-o:保持文件所有者(仅 root 用户有效)。
-D:保持设备文件和特殊文件。
-v, --verbose:详细模式,显示同步过程中的详细信息。建议在手动执行时开启,方便观察过程。
-z, --compress:在传输过程中压缩数据,可以有效减少网络带宽占用,但会增加一点 CPU 负担。
实用场景与命令示例
1. 本地目录同步
将 /path/to/source/ 目录下的所有内容同步到 /path/to/destination/。
重要提示: 源路径 SRC末尾的 / 非常关键。
source/ (带斜杠):表示将 source 目录 内 的所有文件和子目录复制到目标目录。
source (不带斜杠):表示将 source 目录 本身 连同其内容一起复制到目标目录。
示例 A:复制源目录内的内容
Bash
# 操作前请务必确认路径,避免数据覆盖!
# 此命令会将 /home/user/data/ 目录下的 file1.txt, subdir/ 等内容
# 同步到 /mnt/backup/ 目录下
# 最终结果是 /mnt/backup/file1.txt, /mnt/backup/subdir/
rsync -avz /home/user/data/ /mnt/backup/
示例 B:复制源目录本身
Bash
# 操作前请务必确认路径,避免数据覆盖!
# 此命令会将 /home/user/data/ 目录本身同步到 /mnt/backup/
# 最终结果是 /mnt/backup/data/file1.txt, /mnt/backup/data/subdir/
rsync -avz /home/user/data /mnt/backup/
2. 通过 SSH 从本地同步到远程服务器
这是最常见的服务器运维场景之一,例如将本地开发好的网站文件推送到服务器。
Bash
# 务必确认目标路径和权限!
# 将本地 /var/www/my-project/ 目录下的所有文件
# 同步到远程服务器 192.168.1.100 的 /var/www/html/ 目录下
# 使用 root 用户身份登录远程服务器
rsync -avz /var/www/my-project/ [email protected]:/var/www/html/
如果你的远程服务器 SSH 端口不是默认的 22,可以使用 -e 选项指定端口:
Bash
# 假设 SSH 端口为 2222
rsync -avz -e "ssh -p 2222" /var/www/my-project/ [email protected]:/var/www/html/
3. 从远程服务器同步到本地
这个场景常用于备份服务器数据到本地。
Bash
# 务必确认本地备份路径!
# 将远程服务器 192.168.1.100 的 /var/log/ 目录
# 完整同步到本地的 /home/user/server_logs/ 目录下
rsync -avz [email protected]:/var/log /home/user/server_logs/
高级用法与常用选项
4. --delete:删除目标目录中多余的文件
默认情况下,rsync 只会进行增量添加和修改。如果你希望目标目录和源目录保持 完全一致(即源目录中已删除的文件,在目标目录中也一并删除),就需要使用 --delete 选项。
⚠️ 警告:--delete 是一个危险的选项! 使用前请务必再三确认你的源路径和目标路径是否正确,否则可能导致目标目录文件被意外删除。强烈建议先使用 --dry-run 选项进行测试。
Bash
# 将 /home/user/docs/ 的内容完整镜像到 /mnt/backup/docs/
# 如果 /mnt/backup/docs/ 中有而 /home/user/docs/ 中没有的文件,将会被删除
rsync -avz --delete /home/user/docs/ /mnt/backup/docs/
5. --dry-run:演习模式,不实际执行
这是 rsync 一个极其有用的安全功能。使用 -n 或 --dry-run 选项,rsync 会模拟整个同步过程,并列出它 计划 要做的所有文件操作(复制、更新、删除),但不会真正执行任何操作。
在使用 --delete 或执行重要的同步任务前,先用 --dry-run 跑一遍是绝佳的安全习惯。
Bash
# 模拟执行一次带删除的同步,看看会发生什么
rsync -avzn --delete /home/user/docs/ /mnt/backup/docs/
6. --exclude 和 --include:排除或包含文件/目录
当你只想同步特定文件或排除某些临时文件、日志文件时,这两个选项非常有用。
--exclude=PATTERN:排除匹配 PATTERN 模式的文件或目录。
--include=PATTERN:包含匹配 PATTERN 模式的文件或目录(通常与 --exclude 结合使用)。
示例 A:排除单个目录和所有 .log 文件
Bash
# 同步 /var/www/my-project/,但排除 node_modules 目录和所有的 .log 文件
rsync -avz --exclude 'node_modules/' --exclude '*.log' /var/www/my-project/ user@remote:/deploy/
示例 B:使用 --exclude-from 从文件中读取排除列表
如果排除规则很多,可以把它们写在一个文件里,每行一个规则。
exclude-list.txt 文件内容:
node_modules/
.git/
*.log
tmp/
然后执行命令:
Bash
rsync -avz --exclude-from='exclude-list.txt' /var/www/my-project/ user@remote:/deploy/
7. --progress:显示传输进度
当传输大文件时,这个选项非常人性化,它会显示每个文件的传输进度条。
Bash
# 传输大文件时显示进度
rsync -avz --progress large-video-file.mp4 user@remote:/media/
如果你希望看到总的进度,可以使用 --info=progress2。
Bash
# 显示总的传输进度,而不是单个文件的
rsync -avz --info=progress2 /path/to/source/ user@remote:/path/to/dest/
总结
- 始终明确源路径末尾的
/:它决定了是复制目录内容还是目录本身。
- 默认使用
-avz:这个组合能满足 90% 以上的需求。
- 使用
--delete 前,必用 --dry-run 测试:这是防止数据丢失的黄金法则。
- 利用
--exclude:在同步项目代码或备份时,排除版本控制目录 (.git, .svn)、依赖目录 (node_modules) 和临时文件,可以大大提高效率和整洁性。
- 配合
cron 定时任务:将 rsync 命令写入脚本,并添加到 crontab 中,可以轻松实现自动化、无人值守的定时备份。