对于 btrfs 子卷,我有从两个阶段创建的简单增量备份:
btrfs send old/@ > base.btrfs
btrfs send new/@ -p old/@ > update.btrfs
两个源子卷是在不同时间从同一活动安装的子卷捕获的快照。
在目标上,我尝试恢复:
btrfs receive ./ < base.btrfs
btrfs receive ./ < update.btrfs
预期是,前一个命令将创建初始备份阶段的恢复快照,而后者将应用进一步的增量阶段。
前一个命令成功,但后一个命令失败:
ERROR: creating snapshot ./@ -> @ failed: File exists
由于很明显我无法将后一阶段有效地应用于不存在的目标,因此我很困惑为什么该过程会执行此检查,以及预期成功应用更新的原因。
如何将更新阶段应用到恢复初始阶段生成的目标中?
答案1
您不能拥有(如在发送方)多个同名的子卷。
您可以mv
在目标系统上获取基本快照/子卷:
mv @ @.old
btrfs receive ./ < update.btrfs
答案2
自从发布这个问题以来,我已经学到了足够的知识来回答这个问题。
答案分为两部分。
首先,receive
无论新子卷是从子流还是父流创建的,子命令始终会在目标目录中创建一个与原始子卷同名的新条目。因此,目标目录必须为空,至少应具有与原始子卷相同的名称。一种简单的方法是为父子卷和每个子子卷分别创建一个新的空目录。
其次,尽管对子命令的调用不会引用父命令,但只要父命令已恢复到同一分区的子卷,它就可以利用父命令中的必要数据。也就是说,只要先前在父命令的同一分区上调用过子命令,receive
子命令就会对子流产生所需的效果。
一旦父母和孩子被恢复,任何父母都可以被删除而不会损害孩子。
因此,以下将是实现原始目标的有效命令序列:
mkdir _tmp
btrfs receive _tmp/ < base.btrfs
btrfs receive ./ < update.btrfs
btrfs subvolume delete _tmp/@
rmdir _tmp
然后子流的全部内容将可通过 获得./@
。
base.btrfs
当然,如果要保存的子流有多个祖先(例如,有自己的父流),则需要进一步的命令。