1. 挂载基础概念:什么是挂载、文件系统与挂载点的关系、Linux启动流程中的挂载阶段

各位同学好,我是老张。今天咱们正式开始《启动挂载问题排查》的第一章。说实话,挂载这个概念,很多搞了两三年Linux的人,理解得还是模模糊糊的。出了问题就知道mount、umount,但真要排查启动时的挂载失败,往往一头雾水。

这一章,我带你把地基打牢。咱们不讲虚的,就讲三件事:挂载到底是什么、文件系统和挂载点怎么配对、以及Linux开机时挂载是怎么一步步发生的。

1.1 什么是挂载?

挂载,说白了就是把存储设备上的文件系统,接入到目录树的一个目录下。

你想想看,一块硬盘插到服务器上,它本身只是一堆0和1。操作系统怎么访问它?必须通过一个目录作为入口。这个入口,就叫挂载点。

核心定义:挂载(mount)是将一个文件系统附加到当前目录树中某个已存在目录的过程。这个目录就是挂载点。

举个例子:

# 查看当前挂载情况
mount | grep sda1

# 手动挂载一个分区到 /mnt/data
mount /dev/sda1 /mnt/data

# 卸载
umount /mnt/data

我在项目中遇到过好几次,有人以为挂载就是把设备“插上去”就行了。其实不是。设备插上后,你得告诉系统:这个设备上的文件系统,请挂到 /data 这个目录下。系统才知道怎么用。

1.2 文件系统与挂载点的关系

文件系统和挂载点,是一对多的关系。一个文件系统只能挂到一个挂载点,但一个挂载点可以先后挂不同的文件系统(后挂的会覆盖之前的)。

我习惯用一张表来理解它们的关系:

概念 本质 例子
文件系统 存储设备上的数据组织格式 ext4、xfs、btrfs、ntfs
挂载点 目录树中的一个目录 /、/boot、/home、/var
挂载操作 建立文件系统到目录的映射 mount /dev/sdb1 /data

这里有个关键点:挂载点必须是一个空目录,或者至少你不介意它原来的内容被隐藏。为什么?因为一旦挂载上去,原目录下的文件就暂时看不到了。直到卸载后才会恢复。

注意:千万不要把设备挂载到非空目录上,除非你清楚后果。我曾经帮一个同事排查过,他把新硬盘挂到了 /var/log 上,结果所有日志都写到了新分区,旧日志全被“遮住”了。排查了三天才发现。

1.3 Linux启动流程中的挂载阶段

Linux开机,挂载不是一次性完成的。它分了好几个阶段。我画了一张流程图,你看完就明白了。

Linux 启动挂载流程 BIOS/UEFI 阶段 Bootloader 加载内核 内核启动 + initramfs 挂载根文件系统 (/) 执行 /sbin/init (PID 1) systemd 读取 /etc/fstab 挂载所有其他文件系统 关键说明: • initramfs 阶段挂载的是最小根文件系统 • 真正的根文件系统挂载后,initramfs 会切换根 • /etc/fstab 中的挂载项由 systemd 按依赖顺序执行 常见挂载失败点: • 根文件系统设备找不到(驱动缺失) • /etc/fstab 中 UUID 写错或设备不存在 • 挂载点目录不存在或权限错误

嗯,这张图你得存下来。咱们后面的章节,几乎每一章都会回到这张图上来。

1.4 启动挂载的三个关键阶段详解

我把启动挂载拆成三个阶段来讲,这样你排查问题时思路更清晰。

第一阶段:initramfs 中的早期挂载

内核启动后,首先加载 initramfs(初始内存文件系统)。这个阶段的目标只有一个:找到并挂载真正的根文件系统。

initramfs 里包含了一些必要的驱动和工具。比如你的根分区在 NVMe 硬盘上,但内核本身没有 NVMe 驱动,那 initramfs 就得把这个驱动加载上。

我的经验:很多启动挂载失败,都是 initramfs 没生成对。比如你换了硬盘控制器,或者改了根分区类型,但忘了重新生成 initramfs。我建议每次修改了存储相关的内核参数或硬件配置后,都执行一下:

# CentOS/RHEL
dracut -f

# Ubuntu/Debian
update-initramfs -u

第二阶段:切换根(pivot_root)

initramfs 挂载好真正的根文件系统后,会执行 pivot_root 系统调用,把根从 initramfs 切换到真正的根分区。然后 initramfs 被卸载,系统进入真正的用户空间。

这个阶段非常脆弱。如果真正的根文件系统挂载失败,系统就会掉入 emergency shell。你会在屏幕上看到类似这样的提示:

Welcome to emergency mode! After logging in, type "journalctl -xb" to view system logs, "systemctl reboot" to reboot, "systemctl default" or "exit" to boot into default mode.
Give root password for maintenance
(or press Control-D to continue):

我在项目中遇到过好几次,都是因为根分区的 UUID 在 fstab 里写错了,导致 pivot_root 失败。排查方法很简单:在 emergency shell 里用 blkid 查看实际 UUID,然后对比 fstab。

第三阶段:systemd 按 fstab 挂载其他分区

根文件系统挂载成功后,systemd 作为 PID 1 启动。它会读取 /etc/fstab,按照里面的配置挂载所有其他文件系统。

fstab 的格式是这样的:

# <file system>  <mount point>  <type>  <options>  <dump>  <pass>
UUID=abc123       /boot          ext4    defaults  0      2
UUID=def456       /home          xfs     defaults  0      2
/dev/sdc1         /data          ext4    noatime   0      2

这里有个坑:挂载顺序。systemd 会根据 fstab 中的依赖关系自动排序,但如果你有嵌套的挂载点(比如先挂 /data,再挂 /data/logs),必须保证父挂载点先挂载成功。

我曾经踩过的坑:有一次我把 /var 和 /var/log 分别挂到了两个不同的分区,但 fstab 里 /var/log 写在了 /var 前面。结果 systemd 尝试挂载 /var/log 时,/var 还没挂上,直接报错。系统启动后 /var/log 是空的,所有日志都写不进去。排查了一整天才发现是顺序问题。

1.5 挂载相关的关键文件

做启动挂载排查,这几个文件你必须烂熟于心:

文件/目录 作用 排查时关注什么
/etc/fstab 文件系统挂载配置表 UUID、挂载点、选项、顺序
/etc/mtab 当前已挂载的文件系统列表 实际挂载状态(通常是 /proc/mounts 的符号链接)
/proc/mounts 内核视角的挂载信息 最真实、最可靠的挂载状态
/etc/default/grub GRUB 引导配置 root= 参数是否正确指向根分区
/boot/grub2/grub.cfg GRUB 实际使用的配置文件 内核启动参数是否包含正确的根设备

我个人的排查习惯:遇到启动挂载问题,第一步永远是看 /proc/mounts。它比 mount 命令的输出更底层、更准确。第二步看 fstab,对比实际挂载和期望挂载的差异。第三步看 dmesg 或 journalctl,找文件系统相关的错误信息。

1.6 本章小结

这一章咱们把挂载的底子打好了。你记住三句话:

  • 挂载就是给文件系统找个目录入口
  • 启动挂载分三个阶段:initramfs 挂根 → pivot_root 切换 → systemd 挂其他
  • 排查挂载问题,先看 /proc/mounts,再看 /etc/fstab,最后看日志