rsync与scp文件传输实战:从增量同步到断点续传

📅 2026/7/28 13:19:04
rsync与scp文件传输实战:从增量同步到断点续传
1. 项目概述为什么rsync是服务器文件传输的“瑞士军刀”在Linux服务器运维和日常开发中文件传输是个高频且基础的操作。无论是部署代码、同步日志、备份数据还是迁移服务器你总得和文件打交道。新手可能上来就用scp简单直接但一旦遇到网络波动、文件巨大或者需要增量同步的场景scp就显得力不从心了。这时rsync就该登场了。它远不止是一个简单的复制命令而是一个集增量同步、断点续传、权限保持、压缩传输于一身的强大工具。很多人知道它快但未必清楚它为什么快以及如何把它的威力完全发挥出来。这个教程的核心就是带你从“会用”到“精通”。我们不只讲rsync怎么实现断点续传——这是它的核心卖点更会拆解它和scp的组合拳用法。因为在实际工作中没有银弹scp的简单直接和rsync的智能高效往往是互补的。比如你可能先用scp快速传一个小配置文件测试连通性再用rsync同步几个G的应用程序目录。理解两者的差异和适用场景能让你在命令行下处理文件传输时更加游刃有余。2. rsync核心机制深度拆解它凭什么能做到断点续传要玩转rsync尤其是依赖其断点续传功能必须理解它的工作原理。这绝不是简单的“复制粘贴”。2.1 增量同步算法快如闪电的秘诀rsync的核心是一个聪明的算法。它不会傻乎乎地每次都传输整个文件。在传输前发送方源会将文件分割成固定大小的数据块默认大小根据协议版本不同通常是700字节或更大并为每个块计算两个校验和一个快速的32位滚动校验和一个更强的128位MD4校验和。接收方目标如果已存在一个同名文件也会做同样的计算。接着接收方会将自己文件的校验和列表发送给发送方。发送方拿着这个列表与源文件的校验和进行比对。神奇的事情发生了发送方通过滚动校验和可以快速定位到哪些数据块在目标端已经存在。对于已经存在的数据块rsync只传输一个引用“这块我有你也有”对于新增或修改的数据块才传输实际内容。举个例子你有一个10GB的数据库备份文件只修改了最后1MB的数据。使用scp你需要重新传输整个10GB。而使用rsync它通过校验和比对发现只有最后一部分数据块变了于是可能只传输几MB的数据效率天壤之别。这就是为什么同步大文件或经常变化的目录时rsync的速度优势是碾压性的。2.2 “断点续传”的真实含义与实现很多人对“断点续传”有误解认为像下载工具一样在任意中断点都能继续。rsync的断点续传更准确地说是“任务续传”它依赖于两个关键机制--partial 与 --progress 参数默认情况下如果传输中断rsync会删除那些未完全传输成功的临时文件。--partial或-P它同时包含了--partial和--progress参数的作用就是告诉rsync“保留那些部分传输的文件”。这样下次重传时这些半成品文件会被利用起来。临时文件命名规则rsync在传输时会先将数据写入一个以.filename.xxxxxx格式命名的临时文件xxxxxx是随机字符串。只有当整个文件传输并校验完成后才会将这个临时文件原子性地重命名为最终的目标文件名。这个机制保证了目标文件在任何时刻都是一个完整可用的版本不会出现文件一半旧一半新的情况。所以rsync的断点续传流程是首次传输因网络中断留下了.bigfile.gz.abc123。你再次执行相同的rsync -P命令。rsync会检查目标位置发现存在.bigfile.gz.abc123它会从这个临时文件已传输的大小开始继续传输剩余部分并在完成后重命名。这比重新开始传输整个文件要高效得多。注意--partial保留的临时文件不会自动清理。如果传输成功它会被重命名并消失如果传输一直失败你需要手动清理这些以点开头的临时文件避免磁盘空间浪费。2.3 与SCP的本质区别协议与场景scp基于SSH协议它的工作模式非常“朴素”建立SSH加密通道然后读取源文件通过通道写入目标文件。它不进行任何差异比较每次都是完整的字节流传输。它的优势在于极度简单语法直观scp source userhost:dest几乎不需要学习。通用性极强只要SSH能通scp就能用是所有Linux发行版的标配。适合单次、小文件、无脑传输传一个脚本、一个配置文件用scp最快最省心。而rsync可以使用两种协议远程Shell如SSHrsync -e ssh和自身的rsync守护进程模式rsync://。我们通常用的是SSH模式因为它安全且无需额外配置守护进程。在SSH模式下rsync利用SSH建立加密连接但传输的逻辑完全由rsync算法控制。因此你可以把rsync理解为运行在SSH隧道上的、具有智能同步能力的超级cp命令。选择指南传一个nginx.conf用scp。同步一个每天增长几百MB的日志目录用rsync。第一次备份一个项目目录可以用scp或rsync。之后项目有改动需要再次备份必须用rsync。3. rsync断点续传实战从基础命令到高级用法理解了原理我们来上手操作。我会从最简单的场景开始逐步增加复杂度并分享我踩过的坑和总结的技巧。3.1 基础断点续传命令解析最常用、最经典的断点续传命令组合如下rsync -avzP /path/to/local/dir/ userremote_host:/path/to/remote/dir/我们来拆解这个命令里的每一个参数-a归档模式。这是最重要的参数之一它是-rlptgoD的集合意味着递归、保持符号链接、保持权限、保持时间戳、保持属组、保持属主、保持设备文件。备份数据时几乎必用。-v详细模式输出正在传输的文件信息。-z在传输过程中进行压缩这对文本、日志等可压缩文件效果显著能节省带宽但会消耗一些CPU。在千兆内网中传输大量小文件时有时关闭压缩去掉-z反而更快因为压缩/解压耗时可能超过了网络传输节省的时间。-P这是实现“断点续传”体验的关键。它是--partial --progress的简写。--partial保留部分传输的文件如上文所述。--progress显示每个文件的传输进度条。这个进度条对于判断传输状态和网速非常有用。一个至关重要的细节注意源目录路径的结尾斜杠/。rsync /home/data/ userhost:/backup/会将data目录下的所有内容同步到远程/backup/目录下。rsync /home/data userhost:/backup/会将data目录本身包括其名称同步到远程结果会是/backup/data/。 如果你搞反了可能会导致目录结构混乱。我个人的习惯是如果明确想同步目录内容就加上斜杠如果想保持目录树结构就不加。在脚本中为了清晰我倾向于使用绝对路径并明确是否加斜杠。3.2 处理传输中断与手动恢复实战中网络中断很常见。假设你正在同步一个巨大的虚拟机镜像文件ubuntu.iso约4GB传输到一半比如2.1GB时网络断了。中断后的现场在目标服务器的同步目录下你会看到一个类似.ubuntu.iso.4Lg1sM的隐藏临时文件。使用ls -la可以查看它的大小应该接近2.1GB。执行恢复你不需要做任何特殊操作只需原封不动地再次执行上次的rsync -avzP命令。rsync的智能行为rsync会检查目标文件。发现存在完整的ubuntu.iso吗没有。发现存在部分文件.ubuntu.iso.4Lg1sM吗有于是它会从约2.1GB的位置开始继续传输进度条会从大约50%的位置开始增长。传输完成当整个文件传输并校验通过后rsync会删除临时文件.ubuntu.iso.4Lg1sM并将完整的文件呈现为ubuntu.iso。实操心得对于超大型文件数十GB以上使用-P参数看到的进度条是莫大的心理安慰也是判断网络状况的直观依据。如果中断后你手动删除了临时文件那么重传就会从头开始。所以除非你确认要重新开始否则不要轻易清理那些点开头的临时文件。可以使用--timeoutSECONDS参数设置I/O超时时间例如--timeout30避免网络僵死时命令一直卡住。3.3 高级场景排除文件、带宽限制与后台任务真实的运维场景往往更复杂。排除特定文件或目录 你不想同步日志文件或者Git目录。rsync -avzP --exclude*.log --exclude.git/ /src/ userhost:/dst/更复杂的排除规则可以写在一个文件里比如exclude-list.txt*.tmp .cache/ node_modules/ *.iso然后使用--exclude-fromexclude-list.txt参数。限制带宽占用 在业务服务器上做同步不能把网络带宽打满影响线上服务。rsync -avzP --bwlimit5000 /src/ userhost:/dst/--bwlimit5000表示将传输速率限制在大约5000 KB/s约5 MB/s。这个功能在跨公网或限流环境下非常实用。长期运行与后台任务 同步海量数据如整个文件服务器可能需要数小时甚至数天。你不能一直开着终端。使用nohup和nohup rsync -avzP /massive_data/ userhost:/backup/ rsync.log 21 这会让命令在后台运行输出重定向到rsync.log文件即使你关闭SSH连接也不会中断。可以用tail -f rsync.log查看实时日志。更优雅的方式是使用screen或tmux会话。在一个tmux会话中启动rsync然后断开会话连接任务会继续在服务器上运行。之后随时可以重新接入会话查看进度。4. SCP与rsync组合用法实战虽然rsync强大但scp在特定场景下仍有其不可替代的价值。组合使用它们效率倍增。4.1 SCP的快速验证与简单传输场景一快速验证网络与权限在打算进行大型rsync之前先用scp传一个几KB的小文件测试SSH密钥是否生效、路径权限是否正确、防火墙是否开放。这比直接运行一个可能耗时很久的rsync命令来试错要快得多。scp ~/test.txt userremote_host:/tmp/如果成功说明基础环境OK可以放心启动rsync。场景二单向传输少量明确文件当你只需要传两三个明确的文件且确定目标位置没有同名文件或覆盖了也无所谓时scp的命令更简洁。scp app.jar config.yaml userhost:/opt/myapp/SCP的常用参数-r递归复制整个目录。-P port指定SSH端口注意是大写Prsync是小写-e ssh -p port。-C压缩传输类似rsync -z。-l limit限制带宽单位是Kbit/s例如-l 800限制到大约100KB/s。4.2 组合拳案例从SCP到rsync的平滑过渡假设你要将一个正在运行的旧Web服务器old_server上的网站数据迁移到新服务器new_server。初步探查与快速同步首先通过scp将网站的核心配置文件、数据库导出文件等小体积关键数据快速传到新服务器确保基础环境能搭起来。scp -r old_userold_server:/etc/nginx/conf.d/ /tmp/nginx_configs/ scp old_userold_server:/backup/db_latest.sql.gz /tmp/首次全量同步业务低峰期使用rsync进行第一次全量同步。这时数据量最大rsync的压缩和增量优势在首次全量时并不明显但其稳定性、保持权限和进度显示特性依然重要。可以在业务低峰期进行。rsync -avzP old_userold_server:/var/www/html/ /var/www/html/最终增量同步切换前在计划停机切换的窗口需要做最后一次增量同步以捕获第一次全量同步后产生的新数据。这时rsync的增量特性发挥巨大作用同步速度会非常快极大缩短停机时间。rsync -avzP --delete old_userold_server:/var/www/html/ /var/www/html/注意这里使用了--delete参数它会删除目标端有而源端没有的文件确保两端完全一致。使用此参数前务必谨慎最好先加--dry-run参数模拟运行检查哪些文件会被删除。rsync -avzP --delete --dry-run old_userold_server:/var/www/html/ /var/www/html/ delete_plan.txt cat delete_plan.txt # 仔细核对输出这个“SCP快速试探 rsync首次全量 rsync最终增量”的组合流程是我在多次服务器迁移中总结出的高效且稳妥的方法。5. 常见问题排查与性能优化技巧即使掌握了命令在实际操作中还是会遇到各种问题。这里记录了几个最典型的“坑”和解决办法。5.1 权限问题Permission Denied这是最常见的问题尤其在同步涉及系统目录或不同用户时。症状rsync报错Permission denied (13)或failed to open “/path/to/file”: Permission denied。排查与解决SSH密钥认证确保你执行命令的用户在远程主机上有正确的SSH公钥认证。先用ssh userhost测试能否无密码登录。目标路径写入权限确保远程用户对目标目录有写权限。可以尝试ssh userhost touch /path/to/remote/dir/test.tmp来测试。使用sudo如果需要同步的源或目标目录需要root权限有几种方法不推荐使用root用户直接同步风险高。推荐同步到有权限的目录再用sudo移动rsync到/tmp/然后SSH上去执行sudo mv /tmp/src /target/。高级通过--rsync-path参数使用sudorsync -avzP --rsync-pathsudo rsync /src/ userhost:/target/。这要求远程用户配置了无需密码的sudo权限且需在sudoers文件中为rsync命令配置NOPASSWD。5.2 连接超时与中断网络不稳定会导致传输中途失败。症状连接长时间无响应后断开或直接报错Connection reset by peer。排查与解决增加超时和重试使用--timeout和--contimeout参数。--timeout设置I/O超时--contimeout设置连接超时。结合--partial和--progress可以实现断点续传。rsync -avzP --timeout30 --contimeout20 /src/ userhost:/dst/使用持久连接对于需要多次同步的场景可以建立一个SSH主连接Master Connection复用其网络隧道能显著提升后续rsync或scp的速度和稳定性。这需要在~/.ssh/config中配置远程主机Host remote_host HostName 192.168.1.100 User myuser ControlMaster auto ControlPath ~/.ssh/control-%r%h:%p ControlPersist 1h配置后第一次连接会建立主通道一小时内再次连接将复用该通道无需重新握手。5.3 性能瓶颈分析与优化传输速度慢不一定是网络问题。瓶颈可能在磁盘IO如果源或目标服务器磁盘是机械硬盘且正在密集读写rsync的计算和读写操作会成为瓶颈。使用iotop命令观察磁盘利用率。尽量在系统空闲时进行大规模同步。大量小文件拖慢速度rsync对每个文件都需要进行元数据统计、校验和计算传输数十万个小文件时前期准备时间可能远超实际数据传输时间。优化1使用-W(--whole-file) 参数。这个参数会禁用增量校验直接传输整个文件。在高速局域网内延迟低、带宽高对于大量小文件这往往比默认的增量模式更快因为省去了计算和比对校验和的CPU开销。rsync -avzPW /src/ userhost:/dst/ # 注意-PW可以合并为 -aW优化2先打包再传输。对于海量小文件最彻底的办法是先在源端用tar打包成一个文件传输这个打包文件再到目标端解压。# 在源端 tar czf project.tar.gz /path/to/project/ # 传输 rsync -avzP project.tar.gz userhost:/backup/ # 在目标端 ssh userhost tar xzf /backup/project.tar.gz -C /target/path/调整并行度对于可以并行传输的多个独立目录可以写脚本或用xargs启动多个rsync进程但要注意磁盘IO和网络带宽的竞争。5.4 空间不足与inode耗尽磁盘空间不足rsync在传输前不会预先检查目标磁盘空间。传输大文件时可能中途因空间不足而失败。可以使用--dry-run模拟并估算大小或通过df -h命令提前检查。inode耗尽即使磁盘有剩余空间如果文件系统inode用完了常见于存在海量小文件的系统也无法创建新文件。rsync会报错No space left on device。用df -i检查inode使用情况。如果inode耗尽需要清理无用文件或扩容。6. 安全加固与自动化脚本示例在生产环境中使用安全性和自动化是必须考虑的。6.1 使用SSH密钥对与最小权限原则永远不要使用密码进行自动化传输。务必配置SSH密钥对并遵循最小权限原则。生成专用的密钥对为同步任务创建一个单独的密钥不要使用个人账户的默认密钥。ssh-keygen -t ed25519 -f ~/.ssh/rsync_sync_key -N # 生成无密码短语的密钥自动化需要部署公钥将公钥rsync_sync_key.pub的内容添加到远程服务器上用于同步的专用账户的~/.ssh/authorized_keys文件中。限制远程命令在authorized_keys文件中你可以限制该密钥只能运行特定的命令这是非常重要的安全措施。在公钥行前面添加命令限制command/usr/bin/rsync --server --sender -vlogDtprze.iLsf . /backup/,no-port-forwarding,no-X11-forwarding,no-pty ssh-ed25519 AAAAB3NzaC1yc2E...这样即使用户密钥泄露攻击者也只能执行固定的rsync命令无法获得完整的shell权限。命令中的路径和参数需要根据你的实际需求精确设定可以通过在远程执行rsync --server --sender -vlogDtprze.iLsf . /dummy来获取正确的命令字符串。6.2 自动化备份脚本示例下面是一个结合了日志、错误处理、邮件通知的简易自动化备份脚本backup_web.sh。它使用rsync将本地Web目录同步到远程备份服务器并保留7天的日志。#!/bin/bash # 配置变量 SOURCE_DIR/var/www/html BACKUP_USERbackupuser BACKUP_HOSTbackup.server.com BACKUP_DIR/backups/web-$(hostname) LOG_DIR/var/log/rsync_backup LOG_FILE${LOG_DIR}/web_backup_$(date %Y%m%d_%H%M%S).log EMAILadminyourdomain.com # 创建日志目录 mkdir -p $LOG_DIR # 记录开始时间 echo 备份开始于 $(date) $LOG_FILE # 执行rsync同步 rsync -avzP --delete \ --excludecache/* \ --excludetmp/* \ -e ssh -i /home/backupuser/.ssh/rsync_sync_key -o StrictHostKeyCheckingno \ $SOURCE_DIR/ $BACKUP_USER$BACKUP_HOST:$BACKUP_DIR/ $LOG_FILE 21 # 检查rsync执行结果 RSYNC_EXIT_CODE$? if [ $RSYNC_EXIT_CODE -eq 0 ]; then STATUS成功 elif [ $RSYNC_EXIT_CODE -eq 23 ] || [ $RSYNC_EXIT_CODE -eq 24 ]; then # 23: 部分文件传输失败24: 部分文件未传输如权限问题 STATUS部分完成 (退出码: $RSYNC_EXIT_CODE) else STATUS失败 (退出码: $RSYNC_EXIT_CODE) fi echo 备份结束于 $(date)状态$STATUS $LOG_FILE # 如果失败发送邮件报警 if [ $RSYNC_EXIT_CODE -ne 0 ]; then mail -s 【警告】服务器 $(hostname) Web备份失败 $EMAIL $LOG_FILE fi # 清理7天前的日志 find $LOG_DIR -name web_backup_*.log -mtime 7 -delete # 退出脚本返回rsync的退出码 exit $RSYNC_EXIT_CODE脚本要点解析-e “ssh …”指定使用带密钥的SSH连接并禁用严格的主机密钥检查StrictHostKeyCheckingno适用于自动化环境首次需手动确认指纹。RSYNC_EXIT_CODE捕获rsync命令的退出状态码。0表示成功非0表示有错误。不同的错误码代表不同问题可在man rsync中查询。日志与报警所有输出重定向到带时间戳的日志文件。失败时通过mail命令发送日志内容报警需配置好系统邮件发送。日志轮转使用find命令清理旧日志避免磁盘被占满。将这个脚本加入crontab即可实现定时自动备份# 每天凌晨2点执行备份 0 2 * * * /usr/local/bin/backup_web.sh最后关于工具的选择我个人的体会是不要有“工具崇拜”。scp和rsync都是利器关键看场景。对于一次性的、目标明确的小文件搬运scp的简洁是无敌的。而对于任何重复性的、数据量大的、需要保持一致的同步任务rsync的增量能力和稳定性是必须的。把两者的优势结合起来一个用于“探路”和“轻活”一个用于“主力”和“重活”你在Linux服务器上的文件传输效率会提升不止一个档次。在编写自动化脚本时一定要加入足够的错误处理和日志这是线上服务稳定的基石。