rsync文件同步:从备份到迁移的瑞士军刀

搞运维这些年,rsync用得比cp多得多。

增量同步、断点续传、压缩传输,这些特性让它在文件传输场景下几乎无可替代。


为什么用rsync

先看个场景:要把100G的日志目录从A服务器同步到B服务器。

用scp:

bash 复制代码
scp -r /data/logs/ user@B:/data/logs/
# 每次都是全量传输
# 中断了要从头来
# 100G传几个小时

用rsync:

bash 复制代码
rsync -avz /data/logs/ user@B:/data/logs/
# 只传有变化的文件
# 中断了从断点继续
# 传输时压缩,省带宽

第一次可能都是100G,但后续同步可能只要传几百M变化的文件。这就是增量同步的威力。


基础用法

本地同步

bash 复制代码
# 基本格式
rsync [选项] 源目录 目标目录

# 同步目录
rsync -av /data/source/ /data/dest/

# 注意:源目录末尾的斜杠很重要!
rsync -av /data/source/ /data/dest/   # 同步source下的内容到dest
rsync -av /data/source /data/dest/    # 同步整个source目录到dest下

斜杠的区别

bash 复制代码
# 有斜杠:同步目录内容
rsync -av /data/logs/ /backup/logs/
# 结果:/backup/logs/下直接是文件

# 没斜杠:同步整个目录
rsync -av /data/logs /backup/
# 结果:/backup/logs/logs/下才是文件(多了一层)

这个坑我见无数人踩过,记住:通常用有斜杠的写法

远程同步

bash 复制代码
# 推送:本地到远程
rsync -avz /data/logs/ user@remote:/data/logs/

# 拉取:远程到本地
rsync -avz user@remote:/data/logs/ /data/logs/

# 指定端口
rsync -avz -e "ssh -p 2222" /data/ user@remote:/data/

常用选项

bash 复制代码
-a, --archive    # 归档模式,等于 -rlptgoD,保持权限、时间等
-v, --verbose    # 详细输出
-z, --compress   # 传输时压缩
-P               # 等于 --progress --partial,显示进度+支持断点续传
-n, --dry-run    # 模拟运行,不实际执行
--delete         # 删除目标中源没有的文件
--exclude        # 排除文件
--include        # 包含文件
--bwlimit        # 限制带宽

推荐组合

bash 复制代码
# 日常同步
rsync -avzP /source/ /dest/

# 镜像同步(目标完全等于源)
rsync -avz --delete /source/ /dest/

# 首次大量传输(显示进度,支持断点)
rsync -avzP --progress /source/ user@remote:/dest/

排除和包含

排除文件

bash 复制代码
# 排除单个目录
rsync -avz --exclude='logs' /data/ /backup/

# 排除多个
rsync -avz --exclude='logs' --exclude='tmp' --exclude='*.log' /data/ /backup/

# 用排除文件
rsync -avz --exclude-from='exclude.txt' /data/ /backup/

# exclude.txt 内容:
logs/
tmp/
*.log
*.tmp
.git/
node_modules/

包含和排除组合

bash 复制代码
# 只同步特定类型文件
rsync -avz --include='*.conf' --exclude='*' /data/ /backup/

# 同步目录结构+特定文件
rsync -avz --include='*/' --include='*.log' --exclude='*' /data/ /backup/

规则是按顺序匹配的,第一个匹配的规则生效。


删除选项

bash 复制代码
# --delete: 删除目标中多余的文件
rsync -avz --delete /source/ /dest/
# 如果源中删了文件,目标也会被删

# --delete-before: 先删除再传输(默认)
# --delete-during: 边传边删
# --delete-after: 传完再删

# 小心使用!建议先 --dry-run 看看会删什么
rsync -avzn --delete /source/ /dest/

实战场景

1. 定时备份

bash 复制代码
#!/bin/bash
# backup.sh

DATE=$(date +%Y%m%d)
SRC="/data/app/"
DEST="/backup/app/"
LOG="/var/log/backup.log"

echo "=== Backup started at $(date) ===" >> $LOG

rsync -avz --delete \
    --exclude='logs/' \
    --exclude='tmp/' \
    --exclude='*.pid' \
    "$SRC" "$DEST" >> $LOG 2>&1

if [ $? -eq 0 ]; then
    echo "Backup completed successfully" >> $LOG
else
    echo "Backup failed!" >> $LOG
    # 发告警
fi

echo "=== Backup finished at $(date) ===" >> $LOG

加入crontab:

bash 复制代码
# 每天凌晨2点备份
0 2 * * * /opt/scripts/backup.sh

2. 跨服务器迁移

bash 复制代码
# 大量数据迁移,限速避免影响业务
rsync -avzP --bwlimit=50000 /data/ user@newserver:/data/
# --bwlimit=50000 表示限速50MB/s

# 迁移完验证
rsync -avzn /data/ user@newserver:/data/
# 如果输出为空,说明完全一致

3. 增量备份到多版本

bash 复制代码
#!/bin/bash
# 保留7天备份

DATE=$(date +%Y%m%d)
SRC="/data/app/"
DEST_BASE="/backup/app"
LATEST="$DEST_BASE/latest"
BACKUP="$DEST_BASE/$DATE"

# 硬链接方式增量备份
rsync -avz --delete --link-dest="$LATEST" "$SRC" "$BACKUP"

# 更新latest链接
rm -f "$LATEST"
ln -s "$BACKUP" "$LATEST"

# 删除7天前的备份
find "$DEST_BASE" -maxdepth 1 -type d -mtime +7 -exec rm -rf {} \;

--link-dest 是个神器:如果文件没变化,直接硬链接到上一版本,不占空间。这样保留7天备份,实际占用空间只比一份稍多一点。

4. 双向同步(慎用)

bash 复制代码
# 先A到B
rsync -avz --update /data/shared/ user@B:/data/shared/

# 再B到A
rsync -avz --update user@B:/data/shared/ /data/shared/

# --update 只同步更新的文件,避免覆盖

双向同步容易出问题,生产环境建议用专门的同步工具(如Syncthing)或者确定好主从关系。

5. 断点续传大文件

bash 复制代码
# 传输大文件,中途断了可以继续
rsync -avzP --partial largefile.tar.gz user@remote:/data/

# --partial 保留传了一半的文件,不删除
# -P 等于 --partial --progress

rsync daemon模式

除了SSH,rsync还可以以守护进程方式运行,适合内网大量机器同步。

服务端配置

bash 复制代码
# /etc/rsyncd.conf
uid = nobody
gid = nobody
use chroot = no
max connections = 10
log file = /var/log/rsyncd.log
pid file = /var/run/rsyncd.pid

[data]
path = /data
comment = Data directory
read only = no
list = yes
auth users = syncuser
secrets file = /etc/rsyncd.secrets

[backup]
path = /backup
comment = Backup directory
read only = yes
bash 复制代码
# /etc/rsyncd.secrets
syncuser:yourpassword
bash 复制代码
# 权限要设对
chmod 600 /etc/rsyncd.secrets

# 启动
rsync --daemon
# 或者用systemd
systemctl start rsyncd

客户端连接

bash 复制代码
# 格式:rsync://user@host/模块名/路径
rsync -avz syncuser@192.168.1.100::data/ /local/data/

# 或者
rsync -avz rsync://syncuser@192.168.1.100/data/ /local/data/

# 密码可以写文件或环境变量
export RSYNC_PASSWORD="yourpassword"
rsync -avz syncuser@192.168.1.100::data/ /local/data/

daemon模式的好处是不走SSH,配置灵活,适合内网批量同步场景。


性能优化

压缩策略

bash 复制代码
# 已压缩的文件不要再压缩
rsync -avz --compress-level=9 /data/ /backup/  # 压缩级别0-9

# 跳过已压缩格式
rsync -avz --skip-compress=gz/jpg/mp4/zip/rar /data/ /backup/

大量小文件

bash 复制代码
# 大量小文件时,可以先打包
tar czf - /data/logs/ | ssh user@remote "tar xzf - -C /backup/"

# 或者用rsync的 --whole-file 选项
rsync -avz --whole-file /data/ /backup/
# 小文件用whole-file直接传比增量计算快

限制资源

bash 复制代码
# 限制带宽(KB/s)
rsync -avz --bwlimit=10000 /data/ user@remote:/data/

# 限制IO优先级
ionice -c2 -n7 rsync -avz /data/ /backup/

常见问题

1. 权限问题

bash 复制代码
# 保持原权限
rsync -avz /data/ /backup/

# 不保持权限(用目标系统默认)
rsync -rltz /data/ /backup/

# 改变属主
rsync -avz --chown=www:www /data/ /backup/

2. 符号链接

bash 复制代码
# 默认 -a 会复制软链接本身
rsync -avz /data/ /backup/

# 复制软链接指向的文件
rsync -avzL /data/ /backup/

# 跳过软链接
rsync -avz --no-links /data/ /backup/

3. 校验数据完整性

bash 复制代码
# 用校验和对比,更准确但更慢
rsync -avzc /data/ /backup/
# -c 使用checksum而不是时间+大小

# 验证同步结果
rsync -avzn --checksum /data/ user@remote:/data/

4. 空目录

bash 复制代码
# rsync默认不创建空目录(没文件可同步)
# 加 -d 选项
rsync -avzd --include='*/' --exclude='*' /data/ /backup/

与其他工具对比

场景 推荐工具
单次传文件 scp
增量同步 rsync
实时同步 lsyncd (rsync+inotify)
相关推荐
爱勇宝7 小时前
第 1 章:别把“需求文档”当成真正的需求
前端·后端·程序员
IT_陈寒12 小时前
闭包陷阱让我加了两天班,JavaScript你真行
前端·人工智能·后端
易协同低代码13 小时前
通达OA核心类库TD类深度解析
后端
Gopher_HBo13 小时前
Go语言学习笔记(十八)Gin处理Session
后端
谭光志14 小时前
工具塞满上下文窗口怎么办?深度拆解 AI Agent Tool Search 按需加载实现原理
前端·后端·ai编程
她说..14 小时前
Java 默认值设置方式
java·开发语言·后端·springboot
foggyprojects14 小时前
从0开始,一句话启动AI DataAgent
后端·数据分析·ai编程
郡杰14 小时前
一些基础和问题解决
后端
陈随易14 小时前
前端项目部署只要30秒
前端·后端·程序员
YIAN14 小时前
从零手写文件读取 MCP 服务:一文吃透 Model Context Protocol 全链路通信原理
前端·后端·mcp