# Linux命令-rsync(远程/本地文件同步 ------ 增量传输的备份与镜像神器)
-
- [🔰 简介](#🔰 简介)
-
- [📖 语法](#📖 语法)
- [⚙️ 选项](#⚙️ 选项)
-
- [💡 示例](#💡 示例)
-
- [示例 1:本地目录同步(基本用法)](#示例 1:本地目录同步(基本用法))
- [示例 2:推送到远程服务器](#示例 2:推送到远程服务器)
- [示例 3:从远程拉取到本地](#示例 3:从远程拉取到本地)
- [示例 4:镜像同步(删除目标多余文件)](#示例 4:镜像同步(删除目标多余文件))
- [示例 5:文件过滤与排除](#示例 5:文件过滤与排除)
- [示例 6:限速与断点续传](#示例 6:限速与断点续传)
- [示例 7:实际运维场景集合](#示例 7:实际运维场景集合)
- [⚠️ 注意](#⚠️ 注意)
-
- [源路径末尾 `/` 的含义(极易混淆!)](#源路径末尾
/ 的含义(极易混淆!))
- [rsync vs scp vs cp 对比](#rsync vs scp vs cp 对比)
- 常见陷阱与排查
- [📝 总结](#📝 总结)
- [📚 相关命令](#📚 相关命令)
快速参考 :rsync 是 Linux 系统中最强大的文件同步和传输工具。它采用独有的增量传输算法------只传输源和目标之间的差异部分,极大节省带宽和时间。支持本地同步、远程推送/拉取、SSH 隧道传输、daemon 模式,并具备断点续传、文件过滤、带宽限制、删除多余文件等生产级特性。是系统备份、文件分发、网站部署、数据迁移的首选工具。
🔰 简介
rsync 由 Andrew Tridgell 和 Paul Mackerras 开发,其核心创新在于 "rsync 算法":将文件分块,计算每块的校验和,只传输源端和目标端不同的块。这意味着对一个 10GB 文件,即使只改动了最后 1KB,也只传输那 1KB。
六种使用模式
| 模式 |
语法 |
说明 |
| 本地到本地 |
rsync [选项] 源 目标 |
同主机内目录/文件同步 |
| 本地到远程 |
rsync [选项] 源 用户@主机:目标 |
Push:推送文件到远程 |
| 远程到本地 |
rsync [选项] 用户@主机:源 目标 |
Pull:从远程拉取文件 |
| 远程到远程 |
rsync [选项] 用户@主机A:源 用户@主机B:目标 |
通过本地中转 |
| Daemon 模式 |
rsync [选项] 用户@主机::模块/路径 |
直接连接 rsync 服务 |
| SSH 隧道 |
rsync [选项] -e ssh 源 目标 |
通过 SSH 加密传输 |
安装位置
# 查看 rsync 路径和版本
which rsync
# 输出:/usr/bin/rsync
rsync --version | head -3
# 输出:
# rsync version 3.1.2 protocol version 31
# Copyright (C) 1996-2015 by Andrew Tridgell, Wayne Davison, and others.
# Web site: http://rsync.samba.org/
# 安装(大多数发行版默认安装)
# CentOS/RHEL
sudo yum install rsync
# CentOS/RHEL 8+
sudo dnf install rsync
# Debian/Ubuntu
sudo apt install rsync
# 查看配置文件路径
ls /etc/rsyncd.conf 2>/dev/null || echo "daemon 模式配置文件不存在(需手动创建)"
📖 语法
rsync [选项] 源 目标
源和目标格式:
| 格式 |
说明 |
/path/to/dir |
本地路径 |
user@host:/path |
远程路径(SSH 方式) |
user@host::module/path |
远程路径(daemon 方式) |
rsync://user@host/module/path |
URL 格式(daemon 方式) |
[USER@]HOST::SRC [USER@]HOST::DEST |
远程到远程(本地中转) |
⚙️ 选项
核心选项(必须掌握)
| 选项 |
说明 |
-a, --archive |
归档模式(最常用!) 等价于 -rlptgoD |
-v, --verbose |
详细输出 |
-z, --compress |
传输时压缩数据 |
-P |
等价于 --partial --progress(断点续传 + 进度) |
-h, --human-readable |
人类可读的大小格式(如 1.5GB) |
-n, --dry-run |
模拟运行(预览将要进行的操作,不实际传输) |
-a 归档模式的分解
| 子选项 |
说明 |
-r, --recursive |
递归目录 |
-l, --links |
保留符号链接 |
-p, --perms |
保留权限 |
-t, --times |
保留修改时间 |
-g, --group |
保留组 |
-o, --owner |
保留所有者(需 root) |
-D |
等价于 --devices --specials(保留设备文件和特殊文件) |
高级选项
| 选项 |
说明 |
--delete |
⚠️ 小心使用 删除目标端多余的文件(镜像同步) |
--delete-excluded |
同时删除被排除的文件 |
--delete-before |
传输前先删除(节省目标空间) |
--exclude 模式 |
排除匹配的文件/目录 |
--exclude-from 文件 |
从文件读取排除模式列表 |
--include 模式 |
包含匹配的文件/目录 |
--bwlimit 速率 |
限制传输带宽(单位 KB/s,如 --bwlimit=10000 即 10MB/s) |
-e, --rsh 命令 |
指定远程 Shell(如 -e "ssh -p 2222") |
--partial |
保留未完整传输的文件(断点续传基础) |
--progress |
显示传输进度 |
--stats |
传输完成后显示统计信息 |
-x, --one-file-system |
不跨越文件系统边界 |
-u, --update |
跳过目标端更新的文件 |
--max-size 大小 |
限制最大文件大小 |
--min-size 大小 |
限制最小文件大小 |
--remove-source-files |
传输成功后删除源文件(相当于移动) |
--chmod 权限 |
设置目标文件权限(如 --chmod=D0755,F0644) |
--log-file 文件 |
将输出记录到日志文件 |
💡 示例
示例 1:本地目录同步(基本用法)
# 准备工作:创建测试目录和文件
mkdir -p /tmp/rsync_test/source
cd /tmp/rsync_test/source
mkdir -p dir1 dir2 dir3
echo "Hello from file1" > file1.txt
echo "Hello from file2" > file2.txt
echo "Hello from file3" > dir1/file3.txt
echo "Config data" > config.conf
# 查看源目录结构
find /tmp/rsync_test/source -type f
# 输出:
# /tmp/rsync_test/source/file1.txt
# /tmp/rsync_test/source/file2.txt
# /tmp/rsync_test/source/config.conf
# /tmp/rsync_test/source/dir1/file3.txt
# 基本同步(保留目录结构、权限、时间戳)
rsync -av /tmp/rsync_test/source/ /tmp/rsync_test/dest/
# 输出:
# sending incremental file list
# ./
# config.conf
# file1.txt
# file2.txt
# dir1/
# dir1/file3.txt
# dir2/
# dir3/
#
# sent 558 bytes received 124 bytes 1,364.00 bytes/sec
# total size is 58 speedup is 0.09
# 验证目标目录
ls -la /tmp/rsync_test/dest/
# 输出:
# drwxr-xr-x 5 user group 100 Jun 14 14:30 .
# drwxr-xr-x 4 user group 80 Jun 14 14:30 ..
# -rw-r--r-- 1 user group 13 Jun 14 14:30 config.conf
# drwxr-xr-x 2 user group 40 Jun 14 14:30 dir1
# drwxr-xr-x 2 user group 40 Jun 14 14:30 dir2
# drwxr-xr-x 2 user group 40 Jun 14 14:30 dir3
# -rw-r--r-- 1 user group 18 Jun 14 14:30 file1.txt
# -rw-r--r-- 1 user group 18 Jun 14 14:30 file2.txt
示例 2:推送到远程服务器
# 将本地 /data/web/ 推送到远程服务器的 /var/www/
rsync -avz /data/web/ user@web-server:/var/www/
# 输出:
# sending incremental file list
# ./
# index.html
# style.css
# script.js
# images/
# images/logo.png
# images/banner.jpg
#
# sent 2,456,789 bytes received 156 bytes 491,389.00 bytes/sec
# total size is 2,450,000 speedup is 1.00
# 带进度条的推送(推荐日常使用)
rsync -avzP /data/web/ user@web-server:/var/www/
# 输出:
# sending incremental file list
# ./
# index.html
# 3,456 100% 0.00kB/s 0:00:00 (xfr#1, to-chk=4/6)
# style.css
# 12,789 100% 12.49MB/s 0:00:00 (xfr#2, to-chk=3/6)
# script.js
# 45,678 100% 22.30MB/s 0:00:00 (xfr#3, to-chk=2/6)
# images/logo.png
# 234,567 100% 19.12MB/s 0:00:00 (xfr#4, to-chk=1/6)
# images/banner.jpg
# 2,160,345 100% 17.85MB/s 0:00:00 (xfr#5, to-chk=0/6)
#
# sent 2,458,912 bytes received 115 bytes 4,918,054.00 bytes/sec
# total size is 2,450,000 speedup is 1.00
# 测试大文件增量同步(第二次传输几乎瞬间完成)
rsync -avh --stats /data/web/ user@web-server:/var/www/
# 输出:
# sending incremental file list
#
# Number of files: 6 (reg: 5, dir: 1)
# Number of created files: 0
# Number of deleted files: 0
# Number of regular files transferred: 0 # 没有文件被传输!
# Total file size: 2.39M bytes
# Total transferred file size: 0 bytes # 传输了 0 字节!
# Literal data: 0 bytes
# Matched data: 0 bytes
# File list size: 0
# File list generation time: 0.001 seconds
# File list transfer time: 0.000 seconds
# Total bytes sent: 205
# Total bytes received: 108
#
# sent 205 bytes received 108 bytes 626.00 bytes/sec
# total size is 2,450,000 speedup is 7,827.48
示例 3:从远程拉取到本地
# 从远程服务器拉取数据
rsync -avz user@db-server:/var/backups/ /local/backups/
# 输出:
# receiving incremental file list
# ./
# db_backup_20260601.sql.gz
# db_backup_20260602.sql.gz
# db_backup_20260603.sql.gz
#
# sent 45 bytes received 125,678,901 bytes 8,378,596.40 bytes/sec
# total size is 125,600,000 speedup is 1.00
# 拉取并显示进度
rsync -avzP user@db-server:/var/backups/db_backup_20260614.sql.gz /local/backups/
# 输出:
# receiving incremental file list
# db_backup_20260614.sql.gz
# 125,678,901 100% 35.67MB/s 0:00:03 (xfr#1, to-chk=0/1)
#
# sent 30 bytes received 125,722,456 bytes 25,144,497.20 bytes/sec
# total size is 125,600,000 speedup is 1.00
# 通过非标准 SSH 端口拉取
rsync -avz -e "ssh -p 2222" user@db-server:/data/ /local/data/
示例 4:镜像同步(删除目标多余文件)
# 准备工作:目标端有多余文件
mkdir -p /tmp/rsync_mirror/src /tmp/rsync_mirror/dst
echo "keep" > /tmp/rsync_mirror/src/keep.txt
echo "remove me" > /tmp/rsync_mirror/dst/old_file.txt
echo "keep" > /tmp/rsync_mirror/dst/keep.txt
# 查看同步前状态
ls -la /tmp/rsync_mirror/src/
# 输出:keep.txt
ls -la /tmp/rsync_mirror/dst/
# 输出:keep.txt old_file.txt
# 预览镜像同步效果(--dry-run 模拟)
rsync -av --delete --dry-run /tmp/rsync_mirror/src/ /tmp/rsync_mirror/dst/
# 输出:
# sending incremental file list
# deleting old_file.txt # 会删除!
# ./
#
# sent 105 bytes received 13 bytes 236.00 bytes/sec
# 执行镜像同步
rsync -av --delete /tmp/rsync_mirror/src/ /tmp/rsync_mirror/dst/
# 输出:
# sending incremental file list
# deleting old_file.txt
# ./
#
# sent 110 bytes received 15 bytes 250.00 bytes/sec
# 验证
ls -la /tmp/rsync_mirror/dst/
# 输出:keep.txt(old_file.txt 已被删除)
# ⚠️ 目标端与源端完全一致!
# 生产环境中使用前务必先 --dry-run
rsync -avz --delete --dry-run /production/data/ backup-server:/backup/data/
# 确认无误后再执行
rsync -avz --delete /production/data/ backup-server:/backup/data/
示例 5:文件过滤与排除
# 准备工作
mkdir -p /tmp/rsync_filter/project
cd /tmp/rsync_filter/project
mkdir -p src dist node_modules .git logs
echo "source" > src/app.js
echo "build" > dist/bundle.js
echo "modules" > node_modules/module.js
echo "git" > .git/HEAD
echo "log" > logs/app.log
echo "log" > logs/error.log
touch README.md package.json
# 排除 node_modules 和 .git 目录
rsync -av --exclude='node_modules/' --exclude='.git/' /tmp/rsync_filter/project/ /tmp/rsync_filter/backup/
# 输出(注意 node_modules 和 .git 未出现):
# sending incremental file list
# ./
# README.md
# package.json
# dist/
# dist/bundle.js
# logs/
# logs/app.log
# logs/error.log
# src/
# src/app.js
#
# sent 456 bytes received 78 bytes 1,068.00 bytes/sec
# 排除所有 .log 文件
rsync -av --exclude='*.log' /tmp/rsync_filter/project/ /tmp/rsync_filter/backup2/
# 输出(无 log 文件):
# ./
# README.md
# package.json
# dist/
# dist/bundle.js
# src/
# src/app.js
# 使用排除文件列表(适合复杂过滤规则)
cat > /tmp/rsync_exclude.txt << 'EOF'
node_modules/
.git/
*.log
dist/
.DS_Store
Thumbs.db
*.swp
*~
EOF
rsync -av --exclude-from=/tmp/rsync_exclude.txt \
/tmp/rsync_filter/project/ /tmp/rsync_filter/backup3/
# 输出:
# ./
# README.md
# package.json
# src/
# src/app.js
示例 6:限速与断点续传
# 限速 10MB/s(防止占满带宽影响其他服务)
rsync -avzP --bwlimit=10000 /data/large_files/ user@remote:/backup/
# 输出:
# large_file.tar.gz
# 2,147,483,648 10% 10.00MB/s 0:03:12 (xfr#1, to-chk=3/4)
# ^^^^^^^^^^^^ 稳定在 10MB/s
# 断点续传:中断后使用相同命令继续
# 第一次传输(模拟中断)
rsync -avP /data/huge_file.iso user@remote:/backup/
# huge_file.iso
# 4,294,967,296 45% 50.00MB/s 0:00:38
# ^C (用户中断:Ctrl+C)
# 重新执行相同命令(自动续传)
rsync -avP /data/huge_file.iso user@remote:/backup/
# huge_file.iso
# 4,294,967,296 45% 50.00MB/s 0:00:38
# (从 45% 继续,而非从 0% 开始!)
# 限速 + 非高峰时段打包传输(脚本示例)
cat > /usr/local/bin/nightly-sync.sh << 'SCRIPT'
#!/bin/bash
# 夜间备份脚本:限速 50MB/s,记录日志
rsync -avzP \
--bwlimit=50000 \
--log-file=/var/log/rsync-backup.log \
--exclude='*.tmp' \
--exclude='.cache/' \
/data/production/ \
backup-server:/nightly-backup/$(date +%Y%m%d)/
echo "$(date): Sync completed with exit code $?" >> /var/log/rsync-backup.log
SCRIPT
chmod +x /usr/local/bin/nightly-sync.sh
示例 7:实际运维场景集合
# === 场景1:网站代码部署 ===
rsync -avz --delete \
--exclude='.git/' \
--exclude='.env' \
--exclude='storage/' \
/local/project/ \
deploy@web-server:/var/www/project/
# 输出:
# sending incremental file list
# deleting old-page.html
# ./
# app/Controllers/NewController.php
# resources/views/
# resources/views/welcome.blade.php
# === 场景2:数据库备份同步 ===
rsync -avzP --remove-source-files \
/tmp/daily_backups/ \
archive@nas-server:/archive/db/$(date +%Y/%m)/
# --remove-source-files 传输成功后删除本地文件(相当于移动)
# === 场景3:Linux 系统迁移 ===
# 将整个系统复制到新磁盘(排除虚拟文件系统)
sudo rsync -avxHAX --progress \
--exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found"} \
/ /mnt/new_disk/
# -x: 不跨文件系统
# -H: 保留硬链接
# -A: 保留 ACL
# -X: 保留扩展属性
# === 场景4:跨服务器目录对比 ===
# 使用 --dry-run 查看差异而不实际同步
rsync -avz --dry-run --itemize-changes \
/data/server_a/ user@server_b:/data/server_a/
# 输出:
# >f+++++++++ new_file.txt # > 表示发送到远程
# .d..t...... existing_dir/ # . 表示未传输(仅属性变化)
# >f.st...... modified_file.txt # s 大小变化,t 时间变化
# === 场景5:使用 daemon 模式 ===
# 服务端 /etc/rsyncd.conf 配置示例
cat > /tmp/rsyncd_example.conf << 'EOF'
uid = nobody
gid = nobody
use chroot = yes
max connections = 10
timeout = 300
[backup]
path = /data/backup
comment = Backup Area
read only = no
list = yes
auth users = backupuser
secrets file = /etc/rsyncd.secrets
[public]
path = /data/public
comment = Public Files
read only = yes
list = yes
EOF
# 客户端使用 daemon 模式拉取
rsync -av rsync://backupuser@nas-server/backup/ /local/backup/
# 或双冒号语法
rsync -av backupuser@nas-server::backup/ /local/backup/
⚠️ 注意
源路径末尾 / 的含义(极易混淆!)
# 准备测试环境
mkdir -p /tmp/slash_test/src/data
touch /tmp/slash_test/src/data/file.txt
# === 不带末尾 /(同步目录本身)===
rsync -av /tmp/slash_test/src /tmp/slash_test/dest1/
# 结果:
find /tmp/slash_test/dest1 -type f
# 输出:/tmp/slash_test/dest1/src/data/file.txt
# 创建了 src 目录本身!
# === 带末尾 /(同步目录内容)===
rsync -av /tmp/slash_test/src/ /tmp/slash_test/dest2/
# 结果:
find /tmp/slash_test/dest2 -type f
# 输出:/tmp/slash_test/dest2/data/file.txt
# 只同步了内容,没有创建 src 目录!
# 记忆口诀:
# /src → 目标中创建 src/(复制这个目录)
# /src/ → 目标中展开 src 的内容(不创建 src 目录本身)
rsync vs scp vs cp 对比
# === scp(安全复制)===
# 适用:简单的一次性文件传输
# 缺点:总是全量传输,不支持增量
scp -r /data/ user@server:/data/
# 输出:逐个文件复制,不检查已有文件
# === cp(本地复制)===
# 适用:本地简单复制
# 缺点:无增量、无远程、无过滤
cp -a /src/ /dst/
# === rsync(智能同步)===
# 适用:备份、镜像、部署、增量传输
# 优势:
# 1. 增量传输(只传差异)
# 2. 断点续传
# 3. 文件过滤
# 4. 删除同步
# 5. 带宽限制
# 6. 支持多种传输协议
# 性能对比示例
# scp:传输修改了 1KB 的 100GB 文件 → 传输 100GB(需要几个小时)
# rsync:传输修改了 1KB 的 100GB 文件 → 传输 ~1KB(几乎瞬间完成)
常见陷阱与排查
# 陷阱1:源路径缺少末尾 / 导致目录嵌套
# 错误:
rsync -av /source dest-server:/backup/
# 结果:/backup/source/...(创建了额外的 source 目录)
# 陷阱2:--delete 误删重要文件
# 始终先用 --dry-run 预览!
rsync -av --delete --dry-run /src/ dest-server:/dst/
# 检查输出的 "deleting ..." 行,确认无误后再去掉 --dry-run
# 陷阱3:权限问题
# 传输到 root 拥有的目录时可能出错
sudo rsync -av --rsync-path="sudo rsync" /src/ user@server:/root/dst/
# 陷阱4:大文件传输中断
# 使用 -P 确保支持断点续传
rsync -avP /large/file user@server:/path/
# 陷阱5:符号链接问题
# -a 已包含 -l(保留符号链接),但如果需要复制实际文件:
rsync -avL --copy-links /src/ /dst/ # -L 跟随并复制链接目标
📝 总结
rsync 是 Linux 运维工具箱中最重要的传输工具之一:
- 核心优势:增量传输 ------ 只传输差异部分,第二次同步几乎瞬间完成
- 归档模式
-a 是日常使用的基础选项,保留所有属性
-P(进度 + 断点续传)在大文件或网络不稳定时至关重要
--delete 实现镜像同步,但务必先用 --dry-run 预览
- 路径末尾
/ 决定是同步目录本身还是目录内容,易混淆但极关键
- 六种模式涵盖了从本地复制到远程 daemon 的所有场景
掌握了 rsync,就掌握了 Linux 下最高效的数据传输方式。
📚 相关命令
| 命令 |
说明 |
scp |
基于 SSH 的简单安全文件复制(全量) |
cp |
本地文件复制 |
mv |
移动/重命名文件 |
tar |
归档工具(常与 rsync 配合备份) |
ssh |
rsync 远程传输的底层隧道 |
cron |
定时任务(配合 rsync 实现周期性备份) |
lsyncd |
基于 rsync + inotify 的实时同步工具 |
rclone |
云存储同步工具(rsync 的云版本) |