VPN 上的 rsync:复用已断传输的重试
掉线的隧道终结的是连接,不是数据。用 --partial-dir 保留片段,重跑同一次复制,并在发布前校验文件。
你的上传在十二吉字节归档的第四吉字节处停滞,从下载管理器那里学来的习惯会说按下续传。rsync 不会续传 TCP 流,因为那条流已经随隧道的最后一次重传一起消失了。它能做的是保留已经收到的字节,把它们当作下一次尝试的基础,这是另一套规则下的另一种机制。你选的标志决定这种复用到底会不会发生。
重试重建的是状态,不是续传流
当 SSH 会话掉线,远端只剩下已经刷写到磁盘的部分,别的什么都没有。没有可以重新附着的会话令牌,也没有可以重放的序列号。下一次运行会打开新连接、重新读取源端,并询问接收端已经有什么。
正是最后那个问题让残缺文件值得保留。接收端的副本给了 rsync 可比较的东西,算法只发送它能识别的差异。这仍然是一次新的元数据传输、一遍对源端的重新遍历,所以省下的时间取决于文件有多大比例对得上,而不取决于上一次连接走到了哪里。如果接收端什么都没留,下一次尝试就是完整复制,无论第一次搬了多少吉字节。
决定可复用片段放在哪里
默认行为把残缺文件写在目标路径上,这会让写了一半的归档以最终名字暴露出来。--partial-dir 把它移进你选定的目录,手册把该目录描述为保留下来供后续传输当作数据使用。相对名会在目标目录下解析,当两端可能布局不同时,这正是你要的。
rsync -e ssh --partial-dir=.rsync-partial --info=progress2 -- \
large-archive.bin [email protected]:/srv/incoming/
目标端同样讲究顺序:残缺目录要有足够空间放片段,卷也要有足够空间放完成后的文件。传输中途把目标卷写满会产生一种看起来像网络问题、实际不是的失败,还可能让保留的片段被截断。要在运行开始前检查接收主机的剩余空间,而不是等它失败之后。在同一条 SSH 路径上用 df -h 花几秒钟,是对这个计划最便宜的检验。
权限是更小但真实的问题。一个无关账户可写的残缺目录,会让别人替换掉你下一次运行会当作已收到内容的东西。让它归传输账户所有,也不要放在其他服务对外发布的目录里。
跑同一次复制,而不是更聪明的复制
只有当源端和目标端仍然指向同一个对象时,复用才成立。同样的路径、同样的名字、同样的文件。给源端改名或指向另一个目标目录,就会对着毫无用处的东西重新比较。
期望着差分行为时不要加 --whole-file。这个选项让 rsync 在不做滚动校验和比较的情况下复制整个文件,在快速的本地链路上是合理选择,在一次失败的长途上传之后则恰恰相反。--inplace 也会改变局面:它直接写进目标文件,所以中断留下的文件混着新旧内容,没有可以退回的独立片段。
进度行报告的是传输的累计进度。它不是完成信号。连接还开着时数字就到百分之百,只说明数据已经推出去,不说明接收端已经改名、同步或接受。
只有对得上才接受这个对象
先确认退出状态,然后比较结果,而不是相信没有报错。大小检查能拦住大多数被截断的传输;校验和比较能拦住剩下的,两者都比重新跑一遍上传便宜。
如果归档由下游进程发布,就让那个进程等待已接受的文件。落在受监视目录里、以最终名字出现的保留片段会被下一次扫描捡走,消费方报的错会是输入损坏,而不是一次从未完成的传输。
在接收端确认之前不要动源端。两次尝试之间重新生成归档会改变比较基础,下一次运行要么几乎全部重传,要么产出一个既不符合旧源也不符合新源的文件。
当瓶颈是链路而不是标志时
报头和协议开销是传输成本之一,却很少是决定大文件要多久的那个。重启行为更重要:一种无需手工步骤就能扛过掉线的方法,比一种必须从头开始的更快方法更早交付可用文件。两端的存储和认证路径也属于同一个比较。
用同一个文件和同一个目标比较允许的替代路径,并记下每条路径在中断后从哪里重新开始。这一列告诉你的东西,比任何在短测里测出的峰值速率都多。