rsync实战指南:增量同步、断点续传与备份方案详解 1. 从一次凌晨的备份失败说起很多年前我第一次在生产环境做数据迁移用的还是scp。当时同步一个项目目录几十个G的数据scp 吭哧吭哧跑了快两个小时中途网络抖了一下整个传输直接失败又得从头再来。那时候我就在想如果有一个工具能支持断点续传、增量同步、两端数据校验该多省心。后来接触到 rsync才发现自己之前一直在用锤子拧螺丝。rsyncremote sync是一款开源的文件同步工具几乎所有的 Linux 发行版都默认自带。它的核心能力可以用三句话概括增量传输、断点续传、两端文件状态对比。这些能力让它成为服务器备份、代码发布、数据迁移、镜像同步等场景下的首选工具。这篇内容适合谁看如果你正在维护一台或几台 Linux 服务器需要定期把数据从一台机器同步到另一台机器或者你在做 CI/CD 发布流程需要把构建产物分发到多台服务器又或者你需要一份可靠的远程备份方案rsync 都值得你花半小时彻底搞懂它的用法和原理。这篇博文我会从为什么选 rsync 说起再深入到它的核心同步机制然后给出完整的实操步骤、常用参数、增量备份方案以及我在实际运维中踩过的一些坑。相信我看完之后你会想把手头所有 scp 脚本都改成 rsync。2. 为什么选择 rsync对比 scp、cp、tar 管道同步很多人会问既然 scp 也能远程拷贝文件tar 加管道也能打包传输为什么非得用 rsync这个问题问得好直接决定了你后面会不会主动用它。2.1 scp 和 rsync 的本质区别scp 的同步逻辑是“全量拷贝”不管你目标位置是否已经有相同文件它都会完整传一遍。文件多了、大了传输时间线性增长而且一次中断就得重来。rsync 则不同它会在传输前先对比源和目标的文件列表只有那些大小、时间戳、校验值有差异的文件才会被传输。打个比方你有一个 100 本的书架要搬到隔壁房间。scp 的做法是把 100 本书全部搬过去哪怕对面已经有 99 本一模一样的。rsync 的做法是先看一眼对面缺哪几本只把缺失的那 1 本搬过去。效率差距一目了然。2.2 tar 管道同步的缺陷早年间经常看到有人用tar czf - /data | ssh server tar xzf -这样的命令做远程同步。这种方式确实能传输数据但有几个问题一是没有增量能力每次都是全量打包二是没有断点续传网络一断整个传输作废三是没有任何校验机制传过去的数据对不对完全靠运气。rsync 天然解决了这三个问题。增量传输、断点续传、校验和比对这三个特性组合在一起让 rsync 在绝大多数文件传输场景下都优于 scp 和 tar 管道。2.3 rsync 适用场景与不适合的场景适合的场景服务器数据定期备份到远程存储多台服务器之间同步配置文件或站点目录代码发布时的增量推送迁移服务器时的数据搬移本地目录与远程目录的双向镜像配合双向同步参数不适合的场景实时同步rsync 不是实时工具要配合 inotify 或定时任务才能接近实时大量小文件的首次全量同步每次对比文件列表会有额外开销首次全量传输 10 万个小文件会比 tar 慢跨平台到 Windows 且无额外软件环境的场景rsync 在 Windows 上可用但配置成本比 Linux 高3. rsync 的工作机制增量同步到底是怎么实现的理解 rsync 的原理你才能更好地驾驭它。哪怕只会用命令明白了底层的逻辑遇到问题排查起来也会从容得多。3.1 同步核心文件列表对比rsync 在开始传输前会分别获取源端和目标端的文件列表。它并不是简单比较文件名是否相同而是比较以下几项文件名路径文件大小修改时间mtime可选的文件指纹checksum只要有一项不同这个文件就会被列入待传输列表。这就是 rsync 能做到增量同步的基础。默认比较的是大小和修改时间如果需要更严格的校验可以加上-c参数强制对比校验值。3.2 增量传输的细节断点续传与增量算法对于单个大文件rsync 有一种非常聪明的增量算法。它会把源文件切成固定大小的数据块默认约 700 字节左右对每个数据块计算弱校验和与强校验和。目标端以同样方式对已有文件做分块校验两端交换校验信息后rsync 就能判断出哪些数据块在目标端已经存在只传输缺失的数据块。这个机制在日志文件同步时特别有用。比如你有一个 2G 的日志文件每次新增内容只有几十 M。用 rsync 同步时它只需要传输新增的那部分数据而不是整个文件。单纯依赖修改时间对比可能会漏掉一些文件内容没变但 mtime 被修改的情况所以-c参数在关键业务场景下要按需开启。开启之后会增加一些计算开销但换来的是更可靠的一致性。3.3 传输通道ssh 还是 rsync daemonrsync 有两种工作模式通过 ssh 通道传输默认端口 22也是最常见的用法通过 rsync daemon 模式走独立端口默认 873ssh 模式的好处是无需额外部署服务端只要目标机器有 sshd 服务就能直接用。认证走 ssh 的密钥体系安全可控。daemon 模式下 rsync 自身作为一个服务运行通常在需要开放到公网的场景或没有 ssh 服务的情况下使用但这种模式需要注意访问权限配置只开放必要的模块路径。我个人的建议是能用 ssh 模式就别用 daemon少开一个端口少一份安全风险。只有在内网中有大量备份任务、想统一管理备份策略时才考虑搭 rsync daemon。3.4 rsync 的退出码含义rsync 命令执行后会返回一个退出码。你可能觉得这不重要但在写脚本、做自动化的时候退出码就是判断成功与否的唯一标准。退出码含义0同步成功1语法错误2协议不兼容3文件选择错误4未请求操作5请求操作但未执行6无法删除源文件10套接字 I/O 错误11文件 I/O 错误12rsync 协议数据流错误13诊断信息错误14IPC 代码错误20收到 SIGUSR1/20 或 SIGINT 信号21等待 worker 时收到错误22文件变化导致同步未完成23部分文件传输跳过30超时等待数据35网络连接超时我碰到最多的就是 23 和 11、12。23 通常意味着有部分文件没同步成功往往和权限或文件被占用有关11、12 多为网络问题需要检查带宽和连接稳定性。4. 实操从基本命令到自动化备份方案4.1 基本语法与最小命令rsync 的语法结构是rsync [选项] 源路径 [用户]目标主机:目标路径最基本的用法rsync -av /home/user/data/ backup192.168.1.100:/backup/data/这条命令的含义是把本机/home/user/data/目录下的所有内容同步到远程主机的/backup/data/目录下。注意我在这里写的是data/后面带斜杠而不是data。这个细节非常关键带斜杠把目录里面的内容同步过去等同于data/下的所有内容不带斜杠把目录本身同步过去在目标端会生成data目录里面的内容是源目录的完整拷贝这个区别在同步目录结构时非常重要很多新手在这里栽过跟头。4.2 常用参数速查表rsync 参数多但真正高频使用的就下面一批。参数作用说明-a归档模式等于 -rlptgoD递归传输并保留权限、时间戳、属主、属组、设备文件等-v显示详细输出同步时能看到每个文件的状态-z传输时压缩适合可压缩数据如文本、日志、代码对已压缩格式jpg、mp4没意义-r递归传输目录-a 已包含-u跳过比目标更新的文件常用于防止覆盖--delete删除目标端多余文件使目标端与源端完全一致用于镜像场景--exclude排除指定文件或目录支持通配符--include包含指定文件与 --exclude 组合使用实现白名单逻辑--bwlimit限制传输带宽单位 KB/s避免占满出口带宽--timeout设置 I/O 超时时间超时会自动断开避免同步卡死-n试运行配合 -v 使用可以预览将执行的操作而不会真正同步-c校验文件内容忽略 mtime强制检查文件校验值--partial保留部分传输的文件断点续传的关键参数--progress显示传输进度便于观察大文件传输情况-P等于 --partial --progress常用组合实际使用中我的基准命令都是rsync -avz或rsync -avzP。前者用于大多数同步场景后者用于大文件、长时间传输场景。4.3 场景一服务器备份到远程存储假设你要把一台 Web 服务器的站点目录和数据库备份文件每天同步到另一台备份服务器。rsync -avzP --delete --bwlimit5000 /var/www/html/ backup192.168.1.200:/data/backup/html/这条命令把/var/www/html/下的所有内容增量同步到远程/data/backup/html/启用压缩传输和断点续传删除目标端多余文件并限制带宽不超过 5000KB/s避免影响正常业务流量。4.4 场景二多服务器代码发布代码发布场景最关心的是增量效率和排除无关文件。rsync -avz --exclude.git --excludenode_modules --excluderuntime/logs ./ app10.0.0.5:/var/www/project/排除.git目录避免传仓库元数据排除node_modules避免传输庞大的依赖包排除日志目录避免污染线上环境。发布之前先加 -n 预览一下rsync -avz --exclude.git --excludenode_modules --dry-run ./ app10.0.0.5:/var/www/project/看清单里是不是只有你要同步的文件确认无误后再去掉 --dry-run 执行。4.5 场景三远程拉取到本地有时候源在远程目标在本地rsync -avzP remote192.168.1.100:/data/database/ ./backup/database/配合定时任务就能实现每天自动拉取备份。注意同步方向是由源和目标的相对位置决定的不是固定必须从本地推到远程。4.6 定时同步cron 与脚本组合自动化是 rsync 场景下的基本需求做法也很简单。先写一个备份脚本内容大致如下#!/bin/bash # 定义变量 SOURCE_DIR/home/user/project TARGET_HOSTbackup192.168.1.200 TARGET_DIR/backup/project LOG_FILE/var/log/rsync_project.log # 执行同步 rsync -avz --delete \ --exclude*.tmp \ --excludecache/ \ --timeout300 \ $SOURCE_DIR $TARGET_HOST:$TARGET_DIR $LOG_FILE 21 # 检查退出码 if [ $? -eq 0 ]; then echo $(date %Y-%m-%d %H:%M:%S) 同步成功 $LOG_FILE else echo $(date %Y-%m-%d %H:%M:%S) 同步失败退出码: $? $LOG_FILE fi然后添加到 crontab0 3 * * * /usr/local/bin/backup_project.sh /dev/null 21每天凌晨三点执行一次悄无声息地完成备份。用 ssh key 免密登录就不用在脚本里暴露密码了。提示首次用 crontab 时建议把输出重定向到日志文件别直接丢到/dev/null调试阶段看不到报错会很急人。等稳定运行一周再静默也不迟。5. 增量备份方案硬链接轮询备份定时全量同步的思路虽然简单但有一个隐患如果源端有文件被误删--delete会把目标端的备份也删掉。真正的备份方案要能保留多个历史版本才能在灾难恢复时找回旧数据。5.1 硬链接轮询备份原理rsync 结合硬链接技术可以做出一种经典的轮询备份方案。每次备份时生成一个带时间戳的目录相同内容的文件通过硬链接复用上一次备份的文件存储空间只有新增或修改过的文件才占用新的磁盘空间。这样既保留了完整的历史版本又不会导致磁盘用量线性增长。实现思路是#!/bin/bash # 备份目录 BACKUP_ROOT/backup/project TODAY$(date %Y-%m-%d_%H-%M-%S) PREV$(ls -1 $BACKUP_ROOT | tail -n 1) # 如果存在上一次备份以它为硬链接源 if [ -n $PREV ]; then rsync -av --delete --link-dest$BACKUP_ROOT/$PREV \ /home/user/project/ $BACKUP_ROOT/$TODAY/ else rsync -av /home/user/project/ $BACKUP_ROOT/$TODAY/ fi # 清理超过30天的备份 find $BACKUP_ROOT -maxdepth 1 -type d -name 20* -mtime 30 -exec rm -rf {} \;--link-dest指定了上一次备份目录rsync 在对比文件时会先检查能否以硬链接方式引用目标端的旧文件。能链接就链接不能链接才重新传输。这个方案既保留了多版本又节省磁盘空间。5.2 恢复备份的步骤恢复某个历史版本的备份直接把对应日期的目录拷贝回去rsync -avzP /backup/project/2025-01-15_03-00-00/ app10.0.0.5:/var/www/project/建议目录权限恢复后再测一下服务是否正常备份恢复了不代表应用一定能跑起来数据库类文件尤其要注意一致性。5.3 备份方案中的常见陷阱第一次用硬链接轮询方案时容易忽略一个问题--delete会删掉目标端多余文件但如果目标源目录中有一个文件没有变化硬链接能保住它的存量存储不会有任何问题。不过如果你备份的文件是数据库通过 mysqldump 导出的 SQL 文件每次导出的内容都是新文件硬链接就发挥不出作用了需要结合数据库自身的事务日志或 binlog 才能做真正的增量备份。另外硬链接轮询方案需要源和备份目录在同一个文件系统。因为硬链接不能跨文件系统创建。如果你的备份盘是独立挂载的要确认挂载点下这些备份目录在同一个分区内否则 --link-dest 会失效退化为全量拷贝。6. 常见问题与排查实录任何工具用久了都会遇到各种问题rsync 也不例外。以下是我在实际运维中遇到频率最高的一批问题和解法。6.1 同步速度很慢应该从哪排查遇到速度慢先分清是首次全量同步还是增量同步。首次全量同步的情况下慢是正常的特别是数据量大、文件多的时候。但如果你确认是增量同步也慢重点排查两个方向网络带宽是否被其他业务占用文件 mtime 是否频繁变化导致大量文件被判定为需要传输我遇到过最隐蔽的情况一个服务每时每刻在更新某些文件的 mtime导致 rsync 每次都会认为文件有变化而重新传输。排查时用rsync -avzc对比一次发现实际内容并没有变化于是确认是 mtime 的问题解法是从应用层调整文件的更新策略或者在同步时禁用 mtime 对比只用校验值对比。6.2 退出码 23 的典型原因退出码 23 表示部分文件没有传输成功。常见原因目标端目录没有写权限源端文件被进程锁定无法读取文件名包含特殊字符导致无法创建排查时在命令里加上-v看哪些文件被跳过或报错。大量文件报权限问题就用-a参数让归档模式保留权限信息并确认目标用户具备写入权限。6.3 断点续传的文件会残留吗rsync 传输过程中断后目标端会留下一个临时文件。使用--partial参数中断时的部分文件会保留为后缀.rsync的临时文件。下次同步时 rsync 会基于这些临时文件续传而不用从零开始。不想要这种临时文件残留在脚本里加一条清理命令find $TARGET_DIR -name *.rsync -delete6.4 --delete 误删数据怎么办这是 rsync 最危险的参数之一。用了--delete之后目标端所有源端不存在的文件都会被删除。如果同步方向搞反数据就彻底没了。我的建议是重要数据同步前先备份目标端目录列表用--dry-run先预览将被删除的文件必要时加上--exclude保护关键文件更稳妥的做法是搭配--backup参数删除前先备份目标侧文件到指定目录rsync -av --delete --backup --backup-dir/backup/deleted/ /source/ /target/这样被删除的文件会先归档到/backup/deleted/而不是直接消失。6.5 如何迁移到新服务器服务迁移时常见操作是把旧服务器数据同步到新服务器rsync -avzP --delete --exclude*.pid --exclude/tmp/ root旧服务器IP:/var/www/ /var/www/注意首次同步时用全量之后可以连续跑两次。第一次跑完可能还有文件在写等业务停掉之后再跑一次增量保证最终一致性。发布前新服务器先验证环境确认没问题再切换流量。6.6 大文件同步超时同步大文件时默认没有超时限制但一旦网络抖动进程可能一直挂着。建议设置--timeout600如果 10 分钟没有任何数据传输就自动断开配合--partial实现可恢复的断点续传。这个组合特别适合机房之间网络不稳定的场景。6.7 中文和特殊文件名处理rsync 默认情况下不支持某些特殊字符的文件名尤其是换行符等控制字符。处理方式是加参数--iconvutf-8,utf-8-mac这个参数主要用于 macOS 与 Linux 之间同步时的编码转换问题。普通 Linux 到 Linux 同步一般不需要但如果两边文件系统编码不一致加上能省不少事。7. 进阶rsync daemon 模式与多目标同步7.1 daemon 模式配置虽然大多数场景我用 ssh 模式就够但如果你在内网要维护大量备份任务daemon 模式值得了解。服务端配置文件/etc/rsyncd.confuid root gid root use chroot yes max connections 10 pid file /var/run/rsyncd.pid log file /var/log/rsyncd.log [backup] path /data/backup/ comment backup share read only no list yes auth users rsyncuser secrets file /etc/rsyncd.secrets hosts allow 192.168.1.0/24/etc/rsyncd.secrets文件写入rsyncuser:密码权限设置为 600chmod 600 /etc/rsyncd.secrets启动服务systemctl start rsyncd systemctl enable rsyncd客户端拉取或推送时使用的是模块名而非路径rsync -avzP rsyncuser192.168.1.100::backup/ /local/backup/7.2 多目标同步策略当你有多个目标服务器需要同步同一份代码时不能简单地在一条命令里指定多个目标。做法是写一个循环脚本#!/bin/bash TARGETS(10.0.0.5 10.0.0.6 10.0.0.7) for host in ${TARGETS[]}; do rsync -avz --delete /release/ app$host:/var/www/project/ /var/log/publish.log 21 echo $(date) $host 同步完成 /var/log/publish.log done多目标同步看似简单但要注意一点如果某个节点同步失败脚本需要跳过或重试不能让失败节点带病上生产。可以在每个节点同步后检查退出码并输出日志便于后续排查。7.3 rsync 安全加固建议rsync 走公网时几点安全建议不要用默认端口修改 daemon 端口或结合防火墙限制来源 IP必须配置密钥认证或强密码策略只开放必要的模块路径别把整个根目录暴露出去禁用--delete在公网上的直接使用误操作风险太高日志定期检查观察异常同步记录8. 我的实战记录与经验沉淀最后分享一下我个人的使用习惯和一些踩坑之后的体会。8.1 我常用的 rsync 命令模板日常运维中常用的命令就这几种我直接列出来供参考。全量镜像同步目录结构保持一致、内容完全镜像rsync -avzP --delete /源目录/ 目标路径/带排除列表的增量发布rsync -avzP --exclude-from/etc/rsync_exclude.txt /构建产物/ root目标IP:/应用目录/大文件断点续传rsync -avzP --partial --timeout600 /大文件 /backup/预览效果不实际执行rsync -avzn /源目录/ 目标路径/查看远端目录列表rsync --list-only 目标路径/8.2 一个真实场景跨机房数据迁移有一次我们需要把近百 GB 的数据库备份数据从 A 机房迁到 B 机房。两个机房之间的专线带宽有限白天还要走业务流量只能后半夜跑。我当时设计了一个分段方案先做一次不限制带宽的预同步利用夜间低峰期拉全量业务切停后再做最后的增量同步。第一次全量因为数据量大实际跑了将近 5 个小时。但因为有--partial中间即使断过一次也能续传没有白费前面的进度。业务停止后的增量同步只传了最近几个小时产生的新文件十几分钟就完成了。整个过程没有动用物理硬盘也没有停机太久这就是 rsync 在迁移场景下的价值。8.3 自动化备份中的脚本小技巧有了 cron 还不够我通常会在备份脚本里加几层保护备份前检测磁盘空间余量不足时先告警再决定是否执行生成单独的日志目录按日期存放日志文件每次备份完成后统计数量变化用diff对比上次的文件列表及时发现异常举个例子# 对比两次备份的文件差异 diff (ls /backup/$(date -d yesterday %F)) (ls /backup/$(date %F))如果发现文件数量异常减少立刻排查是不是应用端出问题了而不是在恢复备份时才发现数据没了。8.4 rsync 的局限与新工具对比说到 rsync 的局限有三个点必须承认实时性不足它本质是定时或手动触发的工具首次全量同步速度不如 tar 管道直接因为需要先扫描文件列表不支持类似数据库 binlog 的变更流式同步如果真有实时同步需求可以看 inotify rsync 组合方案或者用其他开源实时同步工具。但即便如此rsync 在增量同步、跨网络传输稳定性、备份版本管理上依然有着不可替代的位置。定期备份、迁移数据、发布代码这些任务我至今仍主要依赖 rsync。8.5 最后的经验之谈rsync 这二十多年能一直保持生命力核心是因为它解决的是文件同步中最本质的那些问题效率、准确性、健壮性。参数多但只要记住-avzP --delete这条主线再按需叠加排除、限速、超时、预览这些能力就足以应对绝大多数场景。我个人体会最深的一件事是刚开始用 rsync 的时候总觉得--delete很厉害处处想用。后来被它删过一次文件从此养成一个习惯凡是涉及删除操作的同步都会先跑一遍--dry-run看看会被删什么。这个习惯救过我很多次也送给大家。