启用复制设备后,如何验证 rsync 是否正确复制了设备?

tu-*_*duh 5 rsync devices disk-image

这是为什么 rsync 尝试复制已经是最新的文件的扩展

我正在尝试使用--copy-devices补丁rsync复制整个磁盘驱动器并将其作为映像存储在另一台机器上。

该副本似乎已正确运行,但是,当我rsync再次使用相同的值运行时,它似乎每次都会再次复制一些数据。

我跑了rsync,出现了冗长的问题,得到了这个:

$ sudo rsync -vvz --partial --progress --copy-devices /dev/sdb me@otherserver:/backupdisks/mydisk.img
opening connection using: ssh -l me otherserver rsync --server -vvze.Lsfx --partial --copy-devices . /backupdisks/mydisk.img  (11 args)
me@otherserver's password: 
delta-transmission enabled
sdb
320,071,851,520 100%   63.47MB/s    1:20:09 (xfr#1, to-chk=0/1)
total: matches=2441955  hash_hits=2441955  false_alarms=204015955 data=0

sent 188 bytes  received 21,979,001 bytes  2,837.31 bytes/sec
total size is 0  speedup is 0.00
Run Code Online (Sandbox Code Playgroud)

我知道 rsync 按时间确定更改,但是磁盘在 rsync 之间没有更改(无论如何它如何确定磁盘的修改时间?)但是,远程映像上的时间每次都会更新。所以这可能是问题所在。

另一种可能性是磁盘有一个坏扇区,它每次都返回不同的值,并否定正在使用的任何校验和。

我的问题有两个:

  1. 我的映像是否已成功传输?如果成功,为什么我再次运行它时会重新传输大部分磁盘? (这也可以作为我的推论问题的一部分得到部分回答:rsync 输出中的“匹配”、“hash_hits”和“false_alarms”是什么,“data=0”是否意味着成功?

  2. 我是否缺少一个开关来使其正常工作? (也许--checksum?)是否可以列出 rsync 算法使用的块级故障?

meu*_*euh 4

默认情况下,rsync 按大小和时间戳比较文件,但设备没有大小,因此必须使用本技术报告中描述的增量算法来计算差异中描述的增量算法来计算差异。松散地,远程文件被分成选定大小的块,并且这些块的校验和被发回。本地文件同样以块为单位进行校验和,并与列表进行比较。然后,远程设备被告知如何重新组装它必须重新制作文件的块,并且发送不匹配的块的数据。

您可以通过仅针对带选项的 deltasum 算法在级别 3 请求调试输出来看到这一点--debug=deltasum3。您可以指定块大小以-B简化数字。例如,对于已经复制过一次的文件,第二次运行

rsync -B 100000 --copy-devices -avv --debug=deltasum3 --no-W /dev/sdd /tmp/mysdd
Run Code Online (Sandbox Code Playgroud)

生成如下所示的输出,显示每个块的校验和:

count=164 rem=84000 blength=100000 s2length=2 flength=16384000
chunk[0] offset=0      len=100000 sum1=61f6893e
chunk[1] offset=100000 len=100000 sum1=32f30ba3
chunk[2] offset=200000 len=100000 sum1=45b1f9e5
...
Run Code Online (Sandbox Code Playgroud)

然后您可以看到它与其他设备的校验和相当简单地匹配,因为没有差异:

potential match at 0      i=0 sum=61f6893e
match at 0      last_match=0      j=0 len=100000 n=0
potential match at 100000 i=1 sum=32f30ba3
match at 100000 last_match=100000 j=1 len=100000 n=0
potential match at 200000 i=2 sum=45b1f9e5
match at 200000 last_match=200000 j=2 len=100000 n=0
...
Run Code Online (Sandbox Code Playgroud)

最后该data=字段为 0,表示没有发送新数据。

total: matches=164  hash_hits=164  false_alarms=0 data=0
Run Code Online (Sandbox Code Playgroud)

如果我们现在通过覆盖文件的中间部分来损坏副本:

echo test | dd conv=block,notrunc seek=80 bs=100000 of=/tmp/mysdd 
touch -r /dev/sdd /tmp/mysdd
Run Code Online (Sandbox Code Playgroud)

然后 rsync 调试向我们显示了块 80 的新校验和,但没有匹配。我们从第 79 场比赛转到第 81 场比赛:

chunk[80] offset=8000000 len=100000 sum1=a73cccfe
...
potential match at 7900000 i=79 sum=58eabec6
match at 7900000 last_match=7900000 j=79 len=100000 n=0
potential match at 8100000 i=81 sum=eba488ba
match at 8100000 last_match=8000000 j=81 len=100000 n=100000
Run Code Online (Sandbox Code Playgroud)

最后我们data=100000表明必须发送一个全新的数据块。

total: matches=163  hash_hits=385  false_alarms=0 data=100000
Run Code Online (Sandbox Code Playgroud)

对于无法匹配的损坏块校验和,匹配数已减少 1。也许哈希命中率上升是因为我们失去了顺序匹配。


如果我们进一步查看同一份技术报告,会显示一些测试结果和误报 描述为“32 位滚动校验和匹配但强校验和不匹配的次数”。每个块都有一个简单的校验和和一个 md5 校验和(旧版本中为 md4)。简单的校验和很容易使用哈希表进行搜索,因为它是一个 32 位整数。一旦匹配到某个条目,还会比较较长的 16 字节 md5 校验和,如果不匹配则误报,继续搜索。

我的示例使用一个非常小的(且旧的)16MB 的 USB 密钥设备,最小哈希表大小为 2**16,即 65536 个条目,因此当保存我拥有的 164 个块条目时,它非常空。如此多的误报是正常的,而且比其他任何事情都更能表明效率。