我正在尝试设计一个框架,使我可以对 Ubuntu 和根文件系统进行完整的事务升级。
要求是,如果我的升级失败,我希望能够恢复到之前的精确状态。
Ubuntu Core 似乎提供了我所需要的确切功能,但它有很多安全限制,并且与传统 Ubuntu 相比实际上是一个相当不同的系统。
一个选项是使用 2 个分区。我将在第二个分区上安装新版本的操作系统,重新应用所有配置,然后更新 grub 以从该分区启动。
但是,我需要确定每个分区的大小,这并不理想。这也使得在两个版本的操作系统之间共享某些目录变得更加复杂(即,/var
我宁愿/var
从其他地方绑定安装,而不是复制日志)。
我的想法是有一个根目录,里面有一堆空目录/etc
、、/lib
等/opt
,还有一个目录,比如,/versions
其中包含我不同版本的操作系统。例如
/versions/v1/
,/versions/v2/
。
在启动时,启动过程会选择正确的版本,然后将每个子目录绑定挂载到根子目录上。
换句话说,如果我想要从 启动/versions/v2
,它会绑定挂载:
/versions/v2/etc
on /etc
/versions/v2/opt
on/opt
等等。
我想知道的是,这是否是解决这个问题的正确方法,如果是,那么如何实现。
答案1
经过一番研究,我找到了实现我想要的方法。
我必须深入研究 initramfs 映像 ( /boot/initrd.img-...
) 才能找出各种文件系统的挂载方式。ubuntu core 的 initramfs 映像特别有用。
我确定的设计实际上与 ubuntu core 非常相似。我创建了一个初始 ubuntu 安装,执行了我需要的配置,然后使用 进行深度复制cpio
,最后使用 将副本打包到只读 squashfs 文件系统中mksquashfs
。我将把 squashfs 映像存储在新操作系统的主分区上。在加载操作系统期间,我进行了编辑initrd.img
以将我想要的版本的 squashfs 映像安装到 上,然后在其上/root
进行设置,这是一个可写的覆盖层。overlayroot