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

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

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


为什么用rsync

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

用scp:

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

用rsync:

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

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


基础用法

本地同步

# 基本格式
rsync [选项] 源目录 目标目录

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

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

斜杠的区别

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

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

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

远程同步

# 推送:本地到远程
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/

常用选项

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

推荐组合

# 日常同步
rsync -avzP /source/ /dest/

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

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

排除和包含

排除文件

# 排除单个目录
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/

包含和排除组合

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

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

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


删除选项

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

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

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

实战场景

1. 定时备份

#!/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:

# 每天凌晨2点备份
0 2 * * * /opt/scripts/backup.sh

2. 跨服务器迁移

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

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

3. 增量备份到多版本

#!/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. 双向同步(慎用)

# 先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. 断点续传大文件

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

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

rsync daemon模式

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

服务端配置

# /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
# /etc/rsyncd.secrets
syncuser:yourpassword
# 权限要设对
chmod 600 /etc/rsyncd.secrets

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

客户端连接

# 格式: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,配置灵活,适合内网批量同步场景。


性能优化

压缩策略

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

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

大量小文件

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

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

限制资源

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

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

常见问题

1. 权限问题

# 保持原权限
rsync -avz /data/ /backup/

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

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

2. 符号链接

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

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

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

3. 校验数据完整性

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

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

4. 空目录

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

与其他工具对比

场景 推荐工具
单次传文件 scp
增量同步 rsync
实时同步 lsyncd (rsync+inotify)
双向同步 Syncthing
大量小文件 tar+ssh
对象存储同步 rclone

rsync的定位是增量同步,单次传小文件不如scp方便,实时同步不如专门工具。


总结

rsync几个核心用法:

# 基础同步
rsync -avz /source/ /dest/

# 远程同步
rsync -avzP /source/ user@remote:/dest/

# 镜像同步
rsync -avz --delete /source/ /dest/

# 排除文件
rsync -avz --exclude='logs/' /source/ /dest/

# 限速传输
rsync -avz --bwlimit=10000 /source/ /dest/

# 增量备份
rsync -avz --link-dest=/backup/latest /source/ /backup/20241229/

记住两点:

  1. 源目录加斜杠
  2. 先 --dry-run 再执行

有问题评论区聊。


posted @ 2025-12-31 13:28  花宝宝  阅读(6)  评论(0)    收藏  举报