工作中经常会遇到这样的需求:把一台服务器上的目录定期同步到另一台服务器。
如果数据只有几个 GB,直接复制问题不大。但目录到了几百 GB,再加上每天不断新增文件,就不能每次都重新复制一遍。
这次实际需求是:
Windows Server 2012 R2
10.51.8.117
D:\BPM_LIC
│
│ rsync
│ TCP 873
▼
UOS Server 20
10.182.244.51
/data/BMP_LIC源目录最终参与同步的数据约 742GB。
第一次进行全量同步,后续继续执行同一条 rsync 命令,只同步新增和发生变化的文件。
本文不展开太多算法细节,重点说明 rsync 怎么用,以及这套 Windows 到 Linux 的同步环境是怎么搭起来的。
1. rsync 是干什么的#
rsync 是一个文件同步工具,可以做:
- 本地目录之间同步
- Linux 服务器之间同步
- Windows 和 Linux 之间同步
- 全量同步
- 增量同步
- 文件镜像
- 定时备份
它和 scp 最大的使用区别是:
scp
每次执行基本都是重新传文件
rsync
先比较源端和目标端
只传新增或发生变化的数据rsync 默认会根据文件大小、修改时间等信息判断文件是否发生变化。文件没有变化,下一次同步时就会跳过。上传资料中的测试也可以看到,同一个文件第一次执行会传输,第二次再次执行时不会重复复制。
例如源端:
a.pdf
b.pdf
c.pdf目标端已经存在:
a.pdf
b.pdf再次执行 rsync 时,主要只需要处理:
c.pdf这就是日常所说的增量同步。
2. rsync 常见的三种使用方式#
日常运维知道下面三种就够了。
2.1 本地同步#
类似 cp:
rsync -av /data/source/ /backup/例如:
rsync -av /etc/ /backup/etc/2.2 rsync + SSH#
Linux 服务器之间经常这样使用。
推送:
rsync -av /data/ root@192.168.1.20:/backup/拉取:
rsync -av root@192.168.1.20:/backup/ /data/如果 SSH 不是 22 端口:
rsync -av \
-e "ssh -p 22222" \
/data/ \
root@192.168.1.20:/backup/这种方式走 SSH,数据传输是加密的。
2.3 rsync daemon#
另一种常见方式是让目标服务器直接运行 rsync 服务。
格式:
rsync [参数] 源目录 用户@服务器IP::模块名例如:
rsync -av /backup/ rsync_backup@10.0.0.41::backup/注意:
::是两个冒号。
daemon 模式默认监听:
TCP 873不依赖 SSH 22 端口。
上传的 rsync 资料中也是通过 /etc/rsyncd.conf 定义模块,再使用 USER@HOST::MODULE 进行推送和拉取。
我们这次 Windows → Linux 就采用这种方式。
3. 常用参数和命令#
rsync 参数很多,生产中常用的其实没有多少。
| 参数 | 作用 |
|---|---|
-a | 归档模式,递归同步目录并尽量保留文件属性 |
-v | 显示详细过程 |
-n | dry-run,只检查,不真正同步 |
-i | 显示哪些文件发生变化 |
-c | 根据文件内容 checksum 比较 |
--progress | 显示传输进度 |
--partial | 中断后保留未完成文件 |
--stats | 显示同步统计 |
--timeout=600 | 设置超时时间 |
--bwlimit | 限制同步带宽 |
--exclude | 排除指定文件或目录 |
--delete | 删除目标端中源端已经不存在的文件 |
--password-file | 使用密码文件,避免人工输入密码 |
资料中也列出了 --delete、--bwlimit、--partial 和 --password-file 等常用参数。
常用同步命令#
rsync -av --partial --stats source/ destination/只检查哪些文件不同#
rsync -avni source/ destination/严格按文件内容比较#
rsync -avnc source/ destination/-c 会读取文件内容计算校验值,大目录执行起来比较慢,日常增量同步一般没必要每次都加。
--delete 要特别注意#
例如源端:
A
B目标端:
A
B
C执行:
rsync -av --delete source/ destination/目标端的:
C会被删除。
也就是说:
--delete表示:
让目标端尽量和源端保持一致。
上传资料中的例子也是先删除源端文件,再通过 --delete 把目标端对应文件删除。
生产环境第一次用之前建议先:
rsync -avni --delete source/ destination/看看它准备删什么。
4. Windows 到 Linux 同步环境#
这次实际环境如下。
| 项目 | 配置 |
|---|---|
| Windows | Windows Server 2012 R2 |
| Windows IP | 10.51.8.117 |
| Windows目录 | D:\BPM_LIC |
| Linux | UOS Server 20 |
| Linux IP | 10.182.244.51 |
| Linux目录 | /data/BMP_LIC |
| rsync端口 | 873/TCP |
| rsync模式 | daemon |
| Linux rsync版本 | 3.1.3 |
| Windows cwRsync版本 | 3.4.1 |
Linux /data 是一个独立逻辑卷:
df -h /data初始状态:
文件系统 容量 已用 可用 已用%
/dev/mapper/data--vg-data--lv 1.2T 8.4G 1.2T 1%5. Linux 服务端配置#
5.1 创建同步目录#
mkdir -p /data/BMP_LIC创建一个专门负责写文件的系统用户:
useradd -r -s /sbin/nologin rsyncuser授权:
chown -R rsyncuser:rsyncuser /data/BMP_LIC
chmod 755 /data/BMP_LIC检查:
id rsyncuser
ls -ld /data/BMP_LIC结果:
uid=977(rsyncuser) gid=977(rsyncuser)
drwxr-xr-x 2 rsyncuser rsyncuser ... /data/BMP_LIC5.2 配置 /etc/rsyncd.conf#
先备份:
cp -p /etc/rsyncd.conf /etc/rsyncd.conf.bak_20260828配置:
uid = rsyncuser
gid = rsyncuser
use chroot = no
max connections = 10
timeout = 600
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsyncd.lock
log file = /var/log/rsyncd.log
transfer logging = yes
[BMP_LIC]
path = /data/BMP_LIC
comment = Windows BMP_LIC Sync
read only = no
list = yes
auth users = bmp_sync
secrets file = /etc/rsyncd.secrets
hosts allow = 172.16.255.246
hosts deny = *这里需要分清两个用户。
rsyncuser是 Linux 系统用户,负责写:
/data/BMP_LIC而:
bmp_sync只是 rsync 登录认证用户。
Windows 最终用的是:
bmp_sync不是 rsyncuser。
5.3 创建认证密码#
创建:
vi /etc/rsyncd.secrets格式:
bmp_sync:实际密码权限必须是:
chmod 600 /etc/rsyncd.secrets
chown root:root /etc/rsyncd.secrets检查:
ls -l /etc/rsyncd.secrets结果:
-rw------- 1 root root ... /etc/rsyncd.secrets5.4 启动 rsync 服务#
查看系统自带服务:
systemctl cat rsyncd.service当前 UOS 的启动方式:
ExecStart=/usr/bin/rsync --daemon --no-detach "$OPTIONS"启动:
systemctl restart rsyncd.service检查:
systemctl status rsyncd.service确认监听:
ss -lntp | grep 873结果:
LISTEN 0 5 0.0.0.0:873 0.0.0.0:* users:(("rsync",pid=...,fd=5))
LISTEN 0 5 [::]:873 [::]:* users:(("rsync",pid=...,fd=6))设置开机启动:
systemctl enable rsyncd.service5.5 检查服务器防火墙#
服务器本机:
iptables -L结果:
Chain INPUT (policy ACCEPT)
Chain FORWARD (policy ACCEPT)
Chain OUTPUT (policy ACCEPT)firewalld:
systemctl status firewalld状态:
inactive (dead)所以 Linux 本机没有阻止 873/TCP。
但客户端和服务器不在同一网段:
10.51.8.117
↓
10.182.244.51中间仍然要确认路由、防火墙、ACL 或 NAT 是否允许:
10.51.8.117 → 10.182.244.51:873/TCP6. Windows Server 2012 R2 配置 cwRsync#
Windows Server 2012 R2 默认没有 rsync,因此安装 cwRsync。
安装目录:
C:\Program Files\cwRsync程序:
C:\Program Files\cwRsync\bin\rsync.exePowerShell 进入目录:
cd 'C:\Program Files\cwRsync\bin'注意路径包含空格,必须加引号。
PowerShell 执行当前目录程序还需要加:
.\所以正确测试方式:
.\rsync.exe --version结果:
rsync version 3.4.1
protocol version 326.1 Windows 路径怎么写#
Windows 的:
D:\BPM_LIC在 cwRsync 中对应:
/cygdrive/d/BPM_LIC/所以:
D:\BPM_LIC\a.pdf对应:
/cygdrive/d/BPM_LIC/a.pdf这里最后的 / 不要随便去掉。
我们希望:
D:\BPM_LIC\xxx
↓
/data/BMP_LIC/xxx因此源端使用:
/cygdrive/d/BPM_LIC/7. 连通性测试和正式同步#
7.1 第一次访问被拒绝#
Windows 测试:
.\rsync.exe --port=873 `
bmp_sync@10.182.244.51::BMP_LIC第一次报:
@ERROR: access denied to BMP_LIC from UNKNOWN (172.16.255.246)Windows 本机地址实际是:
10.51.8.117但是 Linux 收到的源地址是:
172.16.255.246说明中间经过了 NAT。
实际链路类似:
10.51.8.117
│
│ NAT
▼
172.16.255.246
│
▼
10.182.244.51所以原配置:
hosts allow = 10.51.8.117匹配不到。
最终按照 Linux 实际看到的地址限制:
hosts allow = 172.16.255.246
hosts deny = *重启:
systemctl restart rsyncd.serviceWindows 再次测试:
.\rsync.exe --port=873 `
bmp_sync@10.182.244.51::BMP_LIC开始提示:
Password:输入密码后:
drwxr-xr-x 6 2026/08/28 14:42:35 .说明:
网络
873端口
rsync服务
认证都已经正常。
7.2 先传一个测试文件#
Windows 创建:
'rsync test 2026-08-28' |
Out-File D:\BPM_LIC\rsync_test.txt发送:
.\rsync.exe -av --progress --port=873 `
/cygdrive/d/BPM_LIC/rsync_test.txt `
bmp_sync@10.182.244.51::BMP_LIC/输出:
sending incremental file list
rsync_test.txt
48 100% 0.00kB/s 0:00:00
sent 175 bytes
received 43 bytes
total size is 48Linux 检查:
ls -lh /data/BMP_LIC/
cat /data/BMP_LIC/rsync_test.txt结果:
-rwxr-x--- 1 rsyncuser rsyncuser 48 ... rsync_test.txt
rsync test 2026-08-28说明目录写权限也正常。
7.3 正式同步整个目录#
正式执行:
.\rsync.exe -av `
--partial `
--stats `
--timeout=600 `
--port=873 `
/cygdrive/d/BPM_LIC/ `
bmp_sync@10.182.244.51::BMP_LIC/开始输出:
sending incremental file list
10.51.8.11/
10.51.8.11/bpm_lic/
10.51.8.11/bpm_lic/BPMAttachments/
...
*.jpg
*.pdf
*.pngLinux 可以观察同步进度:
watch -n 5 'du -sh /data/BMP_LIC; df -h /data'同步完成后:
df -h /data已经达到:
文件系统 容量 已用 可用 已用%
/dev/mapper/data--vg-data--lv 1.2T 702G 498G 59%8. 怎么确认以后只同步增量#
全量同步完成后,再执行:
.\rsync.exe -avni --port=873 `
/cygdrive/d/BPM_LIC/ `
bmp_sync@10.182.244.51::BMP_LIC/这里:
-n只检查,不真正同步。
-i显示哪些文件有变化。
实际结果:
Password:
sending incremental file list
sent 24,019,744 bytes
received 253,913 bytes
256,864.10 bytes/sec
total size is 742,867,731,065
speedup is 30,603.87 (DRY RUN)中间没有列出任何文件。
说明 rsync 扫描了整个目录,但没有发现需要继续同步的文件。
这次参与比较的数据总量:
742,867,731,065 bytes约:
742.9 GB以后 Windows 目录如果只新增:
10个PDF
3个JPG再次执行:
.\rsync.exe -av `
--partial `
--stats `
--timeout=600 `
--port=873 `
/cygdrive/d/BPM_LIC/ `
bmp_sync@10.182.244.51::BMP_LIC/rsync 只会处理这些新增或发生变化的文件,不会重新传输已经同步完成的 700 多 GB 数据。
如果只想先看看有哪些增量:
.\rsync.exe -avni --port=873 `
/cygdrive/d/BPM_LIC/ `
bmp_sync@10.182.244.51::BMP_LIC/新文件可能看到:
>f+++++++++ new.pdf修改过的文件可能看到:
>f.st...... old.jpg如果没有任何文件输出,就说明两边目前没有需要同步的增量。
结尾#
这次同步最终形成的是:
Windows Server 2012 R2
10.51.8.117
D:\BPM_LIC
│
│ cwRsync
│ TCP 873
▼
NAT:172.16.255.246
│
▼
UOS Server 20
10.182.244.51
│
│ rsync daemon
▼
/data/BMP_LIC第一次同步的数据量约为:
742.9GB全量完成后通过:
.\rsync.exe -avni --port=873 `
/cygdrive/d/BPM_LIC/ `
bmp_sync@10.182.244.51::BMP_LIC/重新检查,没有发现需要继续同步的文件。
对于这种目录长期增长、数据量较大的场景,rsync 的使用方式其实很简单:
第一次跑全量
↓
以后重复执行同一条命令
↓
只处理新增和变化文件
↓
需要确认时用 -avni 做 dry-run真正需要注意的反而不是 rsync 命令本身,而是几个容易出问题的地方:
Windows 路径转换
目录最后的 /
873 端口
NAT 后的实际源 IP
Linux 目录权限
daemon 认证用户
--delete 的删除风险把这些问题处理好,后面的增量同步基本就是重复执行同一条命令。
