使用只读文件系统读/写 /etc

使用只读文件系统读/写 /etc

我有一个嵌入式项目的设置,我想将根文件系统保持为只读并将系统配置保持在读/写分区上。用户无法安装程序,但可以修改配置。除了目录之外,大部分内容都相当简单/etc。它包含启动时所需的配置(如fstab)以及可以更改的配置(如passwd)。

我不确定前进的最佳选择是什么。我可以有一个默认/etc目录并在启动后挂载到它上面吗?将所有变量配置文件符号链接到读/写分区怎么样?另一个更好的解决方案?为简单起见,请考虑如何使用 Raspberry Pi 来完成此操作。

有些人可能(正确地)问如何处理更新。更新是嵌入式软件知道如何安装的根分区和引导分区的压缩和签名映像。因此,需要只读根文件系统,因为升级时任何更改都会丢失。

答案1

我有两个可行的选择给你。第一个是比较困难的。如果您可以使用 btrfs,第二个应该很容易。

初始化文件系统

如今启动 Linux 的典型方法是使用初始化文件系统。它基本上是一个最小的 rootfs,仅具有挂载真实 rootfs 所需的内容。二进制文件和配置被打包到存储在 /boot 下的存档中,并在系统启动时作为第一个 rootfs 解包到 tmpfs 中。

这意味着您可以有一个引导过程,其中从存档加载临时 rootfs,您可以修改其中内核将调用名为 init 的可执行文件,您可以修改该可执行文件,该可执行文件旨在挂载真正的根并执行其他系统启动操作。

有关这部分的更详细说明,您可以阅读例如Arch 启动过程。 (尤其是第 5 部分(initramfs)和第 6 部分(早期用户空间))

你的机会:initramfs 可以是任何东西,可以做任何事情。这Gentoo 维基让您了解什么是可能的。
不好的部分是:这并不容易。正常的方法是使用一些工具来创建 initramfs,例如initramfs-toolsDebian 或mkinitcpioArch 或dracut其他工具。它们有配置选项,但有一个单独的 /etc 是很特别的。

对于initramfs-tools(我不知道其他工具)添加您自己的挂载/等内容可能是可行的。典型的 Debianinitramfs-tools基本上是一堆 shell 脚本,打包了一个早期的 init,它也只是一个 shell 脚本。

该工具具有可用于将自定义文件添加到 initramfs 的钩子(名称钩子可能有点误导;这些钩子update-initramfs通常在内核更新后创建新的 initrafs 时运行)和在 initramfs 中的不同点执行的脚本。早期的用户空间初始化(又是一个有点误导性的名称,因为我称之为钩子)。

如果你走这条路,祝你好运。如果您想要 Debian 下的 initramfs,您可以使用命令提取一个 initramfs(它们位于 /boot/initrd.image*)unmkinitramfs并研究其他工具如何集成在那里,例如dropbear-initramfs

Btrfs

另一个更简单的选择是使用 btrfs 作为根文件系统。如果您可以选择使用 btrfs,您可以利用其子卷功能,该功能可以设置为只读。

btrfs 子卷可以像单独的文件系统一样安装,但对您来说最好的是它不需要这样做。挂载子卷将自动挂载下面的所有子卷。

您可以非常简单地使 /etc 成为一个单独的子卷。安装后你会做类似的事情

mv /etc /etc-tmp
btrfs subvolume create /etc
mv /etc-tmp/* /etc-tmp/.* /etc
rmdir /etc-tmp

现在 /etc 位于与其他子卷不同的子卷中,您可以使用以下命令将根子卷设置为只读,并且 /etc 保持可写。

btrfs property set -t subvol / ro true

顺便说一句:可以使用相同的方法将 /usr 设为只读。如果您将现有的 /usr 移走,创建子卷,然后当您想将内容移回来时,您会收到“mv:找不到命令”,因为您的 /usr/bin 当前为空,这总是很有趣。

相关内容