因此,在 chroot 中我有一个 /etc/fstab 文件。如果我mount -a
在 chroot 中运行,它会挂载列出的分区。但是,即使使用该auto
选项,它们在进入 chroot 时也不会挂载。
使自动挂载与 chroot 配合使用的最佳方法是什么?我知道一种方法是只放入mount -a
一些启动文件,但如果其工作方式与实际环境类似,效果会更好。(特别是,其中一个挂载点是/usr
,因此我担心除非它在启动过程中足够早地发生,否则它将无法正常工作。)
答案1
事情是这样的:实际上没有启动过程在 chroot 中。
当你运行类似这样的程序时chroot /newroot /bin/sh
,会发生什么/newroot/bin/sh
和正常跑步差不多唯一的区别是,在做所有这些事情之前,它调整进程表中的一些内部状态因此,每当新进程中的某些代码尝试读取路径 时/
,内核都会通过提供 的内容/newroot
而不是 的内容来“欺骗”它/
。而且由于 Linux 系统上的每个绝对路径查找都是从读取目录/
并逐个向下移动开始的,这意味着新进程只会在 下找到内容/newroot
(除了涉及相对路径的一些特殊情况)。但除此之外,运行chroot
本质上只是运行一个正常进程。
如果您想要获得一个像您的 Ubuntu 系统首次启动时那样的启动过程,您需要的不仅仅是chroot
。您需要的是启动一个特殊的 init 进程,该进程将负责启动所有其他系统服务(记录器、计划任务运行器、网络管理器、图形显示管理器等),其中一个就是调用mount -a
。只有在所有这些系统服务启动后,它才会运行您最初希望它运行的东西,比如/bin/sh
。(如果您真的这样做了,您需要一些方法来防止这个新的 init 进程干扰启动 Ubuntu 本身的进程。您基本上会重新发明 Docker。)
就您而言,根据您要执行的操作,您可能需要也可能不需要完整的系统启动过程。如果需要,只需使用 Docker 或类似的东西 - 这就是容器的用途。但如果不需要,您可能可以使用包装器脚本,它将挂载您需要挂载的所有内容,然后启动 shell 或任何您想要的东西。您的包装器脚本可以像这样简单:
#!/bin/sh
mount -a
exec "$@"
如果你将其保存为/newroot/usr/local/sbin/mount-and-run
,则可以像这样使用它:
chroot /newroot /usr/local/sbin/mount-and-run /bin/sh
它将运行chroot
,而后者又将调用mount-and-run
,后者将执行挂载,然后又调用/bin/sh
。(如果您想在mount-and-run
退出之前卸载某些东西,那么情况会变得有点复杂,但这将是另一个问题。)