挂载虚拟文件系统后再执行chroot | AI生成和翻译

首页 2026.07

问题: 在我之前的文章 Recover from a Failed Linux Kernel Boot 的恢复流程中,为什么在执行 chroot /mnt 之前要运行这五个挂载命令?每个命令实际做了什么?

答案:

这五条命令在 /mnt 内部构建了一个你已安装系统功能完整的副本,使得 chroot /mnt 的行为就像你实际启动了那个系统一样。其中一条命令挂载你的真实磁盘;另外四条则将 live USB 的内核提供的虚拟文件系统 嫁接进去。

核心洞察:chroot 改变的是文件系统视图,而非内核

chroot 是一个非常简单的系统调用——它只改变进程所见的 / 路径。在 chroot /mnt 之后,当程序打开 /proc/mounts 时,内核会将其解析为真实文件系统上的 /mnt/proc/mounts。但你仍然在运行 live USB 的内核。磁盘上损坏的内核只是文件,并未执行。

因此问题是:你的磁盘根文件系统中包含 /dev/proc/sys/run 这些 空目录——它们总是在运行时由内核填充,永远不会存储在磁盘上。直接 chroot 到一个裸磁盘挂载点,会得到一个看似正常但实则又聋又瞎的系统:没有设备、没有进程信息、没有内核接口。

逐行解释

sudo mount /dev/nvme0n1pX /mnt

普通的块设备挂载。内核读取该 NVMe 分区上的文件系统(ext4/btrfs),并将其挂载到 /mnt。现在 /mnt/boot/mnt/etc/mnt/usr 就是你的真实已安装系统。(在 Fedora 上使用 btrfs 默认设置时,可能需要 -o subvol=root,并且需要单独执行 mount /dev/nvme0n1pY /mnt/boot/mnt/boot/efi —— 下文会详细说明。)

sudo mount --bind /dev /mnt/dev

绑定挂载(bind mount) 使一个已有的目录树在第二个位置可见——相同的 inode,无需复制,类似于目录树在 VFS 层的硬链接。live 系统上的 /dev 是由内核 + udev 填充的 devtmpfs,包含设备节点:/dev/nvme0n1/dev/null/dev/urandom/dev/tty

chroot 环境中的工具为什么需要它:

没有它:会出现 grub2-install: error: cannot find a device for /boot/efi

sudo mount --bind /proc /mnt/proc

procfs 是内核的进程/状态接口,以文件形式呈现。这里的关键消费者是 /proc/mounts——grub2-mkconfigdracut 读取它来了解挂载情况以及根设备是什么。/proc/cmdline/proc/filesystems/proc/cpuinfo 也会被查询。没有它,grub2-mkconfig 通常会报错:/usr/sbin/grub2-probe: error: failed to get canonical path

sudo mount --bind /sys /mnt/sys

sysfs 是内核的设备模型树——每个设备、驱动和总线都以目录层级呈现。两个关键使用者:

sudo mount --bind /run /mnt/run

一个用于运行时状态的 tmpfs。在 Fedora 上的主要原因:udev 的设备数据库位于 /run/udevdracut / lvm / cryptsetup 会查询它以解析设备属性和 UUID。此外,Fedora 将 /etc/resolv.conf 符号链接到 /run/systemd/resolve/...,因此绑定 /run 可以让你的 chroot 拥有 可用的 DNS——执行 dnf reinstall kernel-core 时需要它。

心智模型

Live USB 内核(运行中)          磁盘(仅文件)
        │                                │
        ├── /dev  ─── bind ──►  /mnt/dev │
        ├── /proc ─── bind ──►  /mnt/proc├── 你损坏的 Fedora
        ├── /sys  ─── bind ──►  /mnt/sys │
        └── /run  ─── bind ──►  /mnt/run │
                                         ▼
                  chroot /mnt = 在 USB 的内核上
                  “启动”磁盘的用户空间

你正在进行一次“弗兰肯斯坦式”启动:live 内核提供硬件访问,磁盘提供用户空间(dnfdracutgrub2-install、你的配置)。这就是整个技巧。

两个实用改进

1. 对 /dev/sys 使用 --rbind + --make-rslave(Arch 的 arch-chroot 就是这样做的):

sudo mount --rbind /dev  /mnt/dev  && sudo mount --make-rslave /mnt/dev
sudo mount --rbind /sys  /mnt/sys  && sudo mount --make-rslave /mnt/sys
sudo mount -t proc /proc /mnt/proc
sudo mount --bind /run   /mnt/run

普通的 --bind 只嫁接顶层挂载,会遗漏子挂载点,比如 /dev/pts(伪终端——某些脚本没有它会挂起)和 /sys/firmware/efi/efivars--rbind 递归绑定整个子树;--make-rslave 防止 chroot 内部的卸载操作传播回 live 会话并导致其崩溃。

2. 在 chroot 之前不要忘记挂载启动分区。 Fedora 将它们分离,而两者对于内核和 GRUB 修复都很重要:

# 先检查分区布局
lsblk -f
sudo mount /dev/nvme0n1pY /mnt/boot        # ext4 /boot,存放 vmlinuz + initramfs
sudo mount /dev/nvme0n1p1 /mnt/boot/efi    # FAT32 ESP,存放 grubx64.efi

如果 /boot 没有挂载,dnf reinstall kerneldracut --regenerate-all 会将内核写入根分区上的一个目录,而固件永远看不到它——修复“成功”,但机器仍然无法启动。这是该恢复流程中最常见的无声故障之一。

或者完全跳过这些繁琐步骤:systemd-nspawn -D /mnt(从 live USB 运行)会自动为你设置所有这些,并提供一个更干净的容器式 chroot 环境。

参考:


AI生成和翻译,但整理分享仍需精力。如果觉得有帮助,欢迎 捐助支持。 微信:@lzwjavaWeChat QR · X: @lzwjava · 打个招呼 👋

返回 捐助