btrfs send
并可receive
用于传输 TB 级的数据,但这些命令不会产生有用的进度输出(即使使用-v
)。我如何检查他们是否成功?
例如,如果我创建一个名为 的新子卷source
,向其中写入 1 GB 随机数据,并将其设置为只读以便可以发送:
# btrfs subvolume create source
# head -c 1G < /dev/urandom > source/data
# btrfs property set source ro true
btrfs send
然后,使用和创建新子卷的副本receive
,但在完成之前中断该过程:
# mkdir destination
# btrfs send source | btrfs receive destination
At subvol source
At subvol source
^C
btrfs subvolume list
不会表明出现任何问题:
# btrfs subvolume list .
ID 1216 gen 370739 top level 5 path source
ID 1219 gen 371244 top level 5 path destination/source
新的子卷可以正常浏览,但其数据显然已损坏:
# exa -lT
- ├── destination
- │ └── source
251M │ └── random_data
- └── source
1.1G └── random_data
btrfs subvolume show destination/source
不会警告我们子卷不完整。它确实表明 s与 sdestination/source
不同,并且看起来s会被设置为s当且仅当运行完成时。UUID
source
destination/source
Received UUID
source
UUID
btrfs receive
是否可以Received UUID
保证创建的子卷btrfs receive
是另一个文件系统上具有该 UUID 的子卷的完整且未经修改的副本?
这部分的man btrfs-send
建议不要,并且似乎暗示destination/source
在上面的示例中使用作为未来快照的父级source
也将无法检测和修复损坏。然而,我仍然不完全清楚这个建议的目的send -c
以及这个建议是否也适用于send -p
.
在增量模式(选项
-p
和-c
)中,发送端和接收端均可用的先前发送的快照可用于减少在不同文件系统上重建已发送快照所需发送的信息量。
-p <parent>
当给出选项时,可以省略该选项-c <clone-src>
,在这种情况下,btrfs send 将从克隆源中确定合适的父级。您不得指定克隆源,除非您保证这些快照在双方(发送方和接收方)上都处于完全相同的状态。
据我所知,snap-sync
,buttersink
和其他类似的工具通过将输出重定向btrfs send
到一系列文件并使用可靠的方法(rsync
而不是简单的管道)传输它们来解决此问题。如果我想开发自己的增量备份解决方案而不依赖于我的发行版未打包的第三方软件,那么这是正确的方法吗?
答案1
TL;DR:如果设置了Received UUID
该readonly
标志,那么不太可能出现问题,除非涉及粗心或恶意。
就像 @timakro 在他的回答中已经说过的那样,Received UUID
在传输完成之前不会设置。旗帜也不是readonly
。再加上流中的每个命令都经过校验和(并且据我所知,发送的元数据还包括校验和)这一事实使得您不太可能最终在接收端得到损坏的快照,readonly
并且Received UUID
放。如果其中任何一个未设置,btrfs 将拒绝使用该快照作为未来的参考btrfs receive
。
如果接收到特制的流,或者某些进程或用户在接收到快照时更改了接收到的快照的内容,则可能损坏接收到的快照的可能是故意损坏。从btrfs-receive
联机帮助页:
错误
btrfs receive 在成功完成后将子卷设置为只读。但是,在接收过程中,对接收路径中的文件或目录具有写入权限的用户可以添加、删除或修改文件,在这种情况下,生成的只读子卷将不是发送子卷的精确副本。
如果目的是创建精确的副本,则应保护接收路径以防止用户访问,直到接收操作完成并将子卷设置为只读。
此外,接收目前并不能很好地验证增量发送流实际上是否有意义,因此特制的发送流有可能创建一个子卷,其中包含指向同一文件系统中任意文件的引用链接。因此,建议用户不要在来自不受信任来源的发送流上使用 btrfs 接收,并在通过不受信任的网络发送受信任的流时保护受信任的流。
还值得注意的是,可以禁用readonly
子卷上的标志,修改内容,然后再次启用它。如果任何一方都这样做了,那么所有的保证都将被抛到九霄云外。
请注意,将输出通过管道传输到文件并传输该文件不会不是提供上述任何保护。就我个人而言,我绝对没有理由认为将 的输出btrfs send
直接通过管道传输到是不安全的ssh
。将流中间存储在文件中的好处是,它可以在不可靠的连接上恢复中断的传输,但它确实不是以数据完整性的方式提供任何保证。
验证接收到的快照是否与发送的快照匹配的一个好(尽管不是万无一失)的方法是使用rsync -avcn --del path/to/sent/snapshot/ user@remote:path/to/received/snapshot/
.
答案2
我有十多个备份系统,完全基于您所说的最后部分。直接管道对我来说从来都不是一个选择,因为我处理的是> 1TB 的网络备份。不能冒失去一点点和浪费时间的风险。
我的最终设置如下。
引导阶段:
- 拍摄第一个完整快照
- 将快照发送到本地文件(-f 选项)
- Rsync 或将快照文件物理媒体传输到远程站点。
- 远程接收第一个快照
增量阶段:
新的本地快照
本地生成并发送到当前快照和上一个快照之间的差异文件
Rsync 到远程站点
远程导入传输的快照文件
清理逻辑(考虑保留、删除旧快照......)
该项目已启动并运行 3 年。在最坏的情况下,当快照不匹配时,删除最后两个(1 个本地,1 个远程)就足以让它在下一次发送时再次工作。
祝你好运
答案3
是否可以
Received UUID
保证创建的子卷btrfs receive
是另一个文件系统上具有该 UUID 的子卷的完整且未经修改的副本?
这Received UUID
字段仅在收到子卷后设置。来自btrfs-progs 源:
@received_uuid:从中接收到此子卷的子卷的 UUID,如果未接收到此子卷,则全为零。请注意,该字段、@stransid、@rtransid、@stime 和 @rtime 是在收到子卷后由用户空间手动设置的。
您还可以在详细模式下观察这一点:
$ btrfs send -v 2020-12-28/ | ssh root@link "btrfs receive -v /mnt/test"
At subvol 2020-12-28/
BTRFS_IOC_SEND returned 0
joining genl thread
At subvol 2020-12-28
receiving subvol 2020-12-28 uuid=778ec7aa-6709-d240-b41d-58d99a6fb9a0, stransid=9
BTRFS_IOC_SET_RECEIVED_SUBVOL uuid=778ec7aa-6709-d240-b41d-58d99a6fb9a0, stransid=9
答案4
我测试了 @timakro 的情况,但它无法正常工作:未完全传输的快照仍然拥有 UUID。
首先,我有两个单独安装的 btrfs 卷:
➜ lsblk|grep loop99
loop99 7:99 0 1G 0 loop
|-loop99p1 259:0 0 512M 0 part /mnt/tmp1
`-loop99p2 259:1 0 486M 0 part /mnt/tmp2
然后,我在第一个 btrfs 卷上创建了一个新的子卷,并在该子卷上创建了一个随机文件:
➜ sudo btrfs subvolume create tmp1/ori
Create subvolume 'tmp1/ori'
➜ sudo dd if=/dev/urandom of=tmp1/ori/test.iso bs=1M count=256
256+0 records in
256+0 records out
268435456 bytes (268 MB, 256 MiB) copied, 1.58701 s, 161.3 MB/s
创建只读快照后,我将其传输到第二个 btrfs 卷并中断传输:
➜ sudo btrfs subvolume snapshot -r tmp1/ori tmp1/snap
Create a readonly snapshot of 'tmp1/ori' in 'tmp1/snap'
➜ sudo btrfs send tmp1/snap | sudo btrfs receive tmp2
At subvol tmp1/snap
At subvol snap
^C
通过哈希,我们可以看到收到的快照与原始快照不同,这意味着它已损坏。
➜ sudo sha256sum tmp1/snap/test.iso
49455edf92d582346215679a52eb6d72f0afa10748ef62f1ce3fc5e417e70f6a tmp1/snap/test.iso
➜ sudo sha256sum tmp2/snap/test.iso
bb30f487a39579dabc768129d59d4abeca25777e4eeb4f41b9beca366d379bab tmp2/snap/test.iso
现在,让我们检查它们的 UUID:
➜ sudo btrfs subvolume list tmp1 -u
ID 257 gen 25 top level 5 uuid b5f8ff5d-fafb-814a-a31b-25bb96c185b5 path ori
ID 258 gen 25 top level 5 uuid d2bfa408-b330-954f-9aa8-138de5030898 path snap
➜ sudo btrfs subvolume list tmp2 -u
ID 256 gen 31 top level 5 uuid 77950b38-812d-3646-88cd-8107def1eced path snap
不完整快照拥有自己的UUID,除了未设置只读标志外,没有指示或提示指示其不完整状态。