如何使用 apt 更新联合文件系统上 Ubuntu 安装的不同层

如何使用 apt 更新联合文件系统上 Ubuntu 安装的不同层

我已在 NAS 上的联合文件系统上安装了 Ubuntu 22.04,并使用 NFS 在无盘客户端上启动它。文件系统中的最低层包含一个最小的可启动版本的 Ubuntu。我可以自行启动该层并使用 进行更新apt

我希望联合文件系统中的上层包含下层未包含的附加软件包。通过启动由下层和上层组成的联合文件系统,且上层为读写,我可以使用 安装这些附加软件包apt

当我必须更新较低文件系统上的软件包时,我的问题就开始了。我使用apt它,它似乎有效。

更新完下层文件系统后,我返回到联合文件系统并尝试更新上层文件系统。但是,apt除了上层文件系统中的软件包外,似乎还想再次更新下层文件系统中的软件包。这会导致上层和下层文件系统出现重复,而这是我不希望看到的。

我尝试过清除上层文件系统/var/lib/apt/var/cache/apt然后再执行apt update,但这并不能解决问题。部分原因是上层文件系统上的软件包引用了下层文件系统上已更新的版本,因此似乎不再存在。因此,apt请尝试重新安装它们,但要在上层文件系统上。

我想过只apt upgrade对上层文件系统执行一个操作,然后检查重复的包并以某种方式强制清除它们,但我还没有找到策略。

我怀疑我已经远远超出了设计的范围apt。有没有apt大神能给我一些指导?我内心的黑客正在考虑/var/lib/dpkg/*用 Perl 脚本进行攻击……

附加信息

该目录/var/lib/dpkg/info/出现在下层和上层。似乎每一层中的版本仅包含安装在同一层中的软件包的信息。由于每个软件包的信息都保存在特定于该软件包的单独文件中,因此将两个目录合并到联合文件系统中会产生所有已安装软件包的单一视图,这正是我所希望的。

但是,这/var/lib/dpkg/status是一个包含所有软件包信息的文本文件,并且唯一可见的合并版本来自上层。任何对下层的后续更改都不会被复制上去,因此不可见。这会导致上层出现问题,因为上层包含对已更新内容的引用,而这些内容实际上已经消失了。

我需要重建吗/var/lib/dpkg/status

回顾过去,但更详细

[这是为预期我将尝试自己回答我的问题而提供的。]

我将尝试自己回答这个问题。请随意评论并指出我的任何错误或错误假设。

回顾一下:我正在尝试创建和维护可通过 NFS 在(许多不同的)无盘设备上启动的 Ubuntu 映像。Ubuntu 映像作为联合文件系统存储在中央 NAS 上并从中央 NAS 导出。我的 NAS 仅支持aufs,所以我在这里使用它。

aufs每个映像在 NAS 上的构建如下:

mount -t aufs o=br:<instance-data>=rw \
                  :<application>=ro \
                  :<local-Ubuntu-config>=ro \
                  :<Canonical-Ubuntu-image>=ro
              none
              <merged-image>            # e.g. /mnt/xxx

每个aufs图像都由 NFS 导出(是的,这是可能的)。

每个无盘客户端都有一个这样的映像。每个映像有 4 个层,定义为分支 ( o=br:...)。由于食人魔有层次,我称这些食人魔

每个层都可以访问其下面的层,因此可以使用安装在下面的任何包和配置。每个层还有自己的附加包和配置。

所有食人魔共享相同的<Canonical-Ubuntu-image>和相同的<local-Ubuntu-config>。这两层可以折叠成一层,但我想在 Canonical 的内容和我的本地配置之间保持明显的区别。

有少数几个<application>(例如网络管理、网络监控、智能家居又名 OpenHAB、开发……)。它们都共享相同的and`,如上所述,但有自己的应用层。

一些怪物是重复的(例如网络管理,OpenHAB),因此它们共享相同的应用程序,但需要为自己的实例进行单独的配置。

不好意思,为什么呢?

目前,我有大约十台 Raspberry Pi,它们在我的网络中执行各种功能,包括使我的房屋正常运转。我把所有的时间都花在确保每台 Pi 都已更新并正常工作上。我试图通过在 Pi 之间尽可能多地共享来减少所需的工作量。

答案1

我将尝试自己回答这个问题。请随意评论并指出我的任何错误或错误假设。

我对原始问题进行了改进,以提供背景信息,使这个答案更容易理解。问题基本上是如何apt食人魔,即无盘客户端的可启动映像,其中映像按联合文件系统的层进行组织。由于我的 NAS 仅支持aufs,因此我在此答案中使用的是联合文件系统。但是,该方法也适用于其他联合文件系统。

一般原则

  1. 每个层都包含一个唯一命名的文件,名为/etc/ogre-d/<name>.pkg,其中包含xargs该层安装的兼容软件包列表。每当在层中添加或删除软件包时,/etc/ogre-d/<name>.pkg 需要相应地更新文件。这是一个手动步骤。请注意,此文件仅包含当前层中安装的软件包的名称(例如,不包含安装在较低层中的软件包)。由于apt对层一无所知,因此它倾向于保留当前层中安装的所有软件包的列表当前的层以及安装在降低层,因此很难从中派生出属于当前层的包/var/lib/dpkg/{info, status}

  2. apt upgrade通过在每个层上单独运行或来更新各层apt install,从最低层开始并逐步向上移动。/etc/ogre-d/<name>.pkg需要在进行过程中在每个层中手动进行更新。

  3. 由于最低层根据定义没有更低的层,因此其维护与apt任何传统的 Ubuntu 安装基本相同。

  4. 最低层以上的层需要特殊处理,因为apt数据库(具体来说/var/lib/dpkg/{info, status})需要从其apt紧邻的下一层数据库中重建,并且需要将当前层的包添加到其中。步骤如下:

    • 在 NAS 上:删除当前层中的/var/lib/dpkg/status/var/lib/dpkg/info(这需要在本机文件系统中而不是联合文件系统中发生,因为否则单元文件系统会将/var/lib/dpkg/status和标记/var/lib/dpkg/info为已删除并在当前层及以上层中屏蔽它们)
    • 在 ogre 中:执行DEBIAN_FRONTEND=noninteractive cat /etc/ogre.d/<name>.pkg | xargs apt reinstall -y以将此层的当前包恢复到其apt数据库(这/var/lib/dpkg/{info, status}将从其较低层重新创建,并添加当前包)
    • 在 Ogre 中:执行任何其他升级或安装,这也将/var/lib/dpkg/{info, status}在当前层中进行相应更新
    • 继续进行下一个更高的级别并重复。
  5. 当 ogre 已完全更新(从最低层到最高层)时,aufs需要重新挂载其联合文件系统(如果是,无论如何)以确保最上层合并目录的完整性,否则该目录将包含在此期间已修改或删除的较低层文件的旧版本。在 NAS 上:mount -t aufs -a -o remount可能就足够了。

需要注意的问题

有些操作(尤其是删除)需要在NAS上文件存储的本机目录下进行,因为(底层文件一旦清空就无法找回,需要重新构建).wh的机制。aufs/var/lib/dpkg/{info, status}

按照@Raffa的尺度[整洁,混乱,肮脏]我会说这个解决方案是整洁的,但也有混乱的。请随意提出不同意见。如果食人魔流行起来,那么提供工具来支持上述步骤是值得的。

相关内容