☰
Linux系统引导流程详解:从BIOS到systemd的启动故障排查指南
2026/10/5 2:43:31 网站建设 项目流程

1. 先从一次“开机卡住”说起:为什么搞懂引导流程这么重要

我早年间踩过一个特别典型的坑,一台跑着CentOS 7的机器,突然某天开机后停在黑屏,左上角光标一闪一闪,就是进不了系统。当时第一反应是“硬盘坏了”,折腾半天准备重装,结果旁边老工程师过来瞄了一眼说:这就是GRUB引导丢了,重建一下就好。十分钟搞定,数据一点没丢。从那以后我就下定决心把Linux系统引导流程彻底吃透,因为引导环节出问题的概率真的很低,可一旦遇到,留给你的反应时间往往就那么多,尤其在生产环境里,每一分钟都在烧钱。

搞懂引导流程,对谁有用?如果你是刚入行的运维,这是理解“系统是怎么活起来”的底层知识;如果你是中级的Linux使用者,这是你排查启动故障时寻找出路的“地图”;哪怕你是准备Linux面试的求职者,“Linux系统引导流程”也是面试官最爱问的一块内容,连内核参数、GRUB修复都可能作为笔试题或现场题。这篇内容不聊教科书式的理论堆砌,我按真实故障排查的视角,把“通电到登录”这条链路上的每个环节拆开,告诉你每一步在做什么、坏了会怎样、怎么修。

我尽量用“说人话”的方式讲,复杂的地方就类比成日常动作,让你看完之后至少能独立处理八成以上的系统启动故障。

2. 引导流程全景:从按下电源键到看见登录界面,系统到底干了啥

2.1 固件阶段:BIOS/UEFI 怎么找到启动设备

这一步是整条链路的起点。按下电源键后,CPU 会先去读固件(BIOS 或 UEFI)里的一段固定代码。说直白点,这段代码的地位相当于“开机大门管理员”,它先自检硬件,然后根据启动顺序去找一个可以引导的设备。这个设备一般是硬盘、U 盘或网卡,找到之后固件会把控制权交给那个设备里的引导程序。

老式 BIOS 和现在的 UEFI 在细节上不太一样。BIOS 时代是直接读取硬盘第一个扇区(MBR,主引导记录)的前 446 字节引导代码,这个扇区如果被破坏,系统就会直接黑屏或提示找不到设备。UEFI 时代则不一样,它会在硬盘上的一个独立分区里找引导文件,这个分区叫 EFI System Partition(ESP),其中存放着引导加载器的 .efi 文件,比如 \EFI\centos\shimx64.efi。UEFI 的好处是更灵活、支持大硬盘、启动校验更严格,但也意味着引导文件是一个“独立文件”,它丢了或者分区格式不对,同样会导致无法启动。

实战里这块最常见的两个故障:一是 MBR 区域被 Windows 或者其他系统覆盖,导致 Linux 无法引导;二是 EFI 分区里的引导文件被清理工具错误删除。处理思路完全不同,前者要用 grub2-install 重写 MBR,后者要重新挂载 EFI 分区并重建引导项,后面我会分别展开。

2.2 GRUB2 引导加载器:它的职责不是“加载内核”这么简单

固件把控制权交给 GRUB2 之后,GRUB2 要干的事比很多人想象的复杂一些。它得先从自己的配置文件(/boot/grub2/grub.cfg)里读取可用的内核列表、默认启动项、内核参数,还要能加载文件系统驱动,识别 /boot 所在分区。等用户选择启动项(或者超时后走默认项),GRUB2 再把对应的内核镜像 vmlinuz 和 initramfs 镜像加载进内存,最后跳转执行。

这里有个关键认知修正:GRUB2 其实是“两段式”的。它先把自己从磁盘里加载到内存,再从这个“迷你环境”里读取配置文件、加载模块。所以当 GRUB 配置文件里引用了不存在的分区 UUID、或者 /boot 分区文件系统损坏时,GRUB 会直接停在命令行界面或 rescue 模式,这并不代表内核坏了,而是引导器自己没找到“下一步该怎么走”。

对故障排查来说,这类问题最烦人的是提示信息不直观。你可能只会看到一个 grub> 提示符,或者 grub rescue> 提示符,这时候第一反应不是慌,而是要确认:GRUB 有没有找到它的配置目录?分区能不能被识别?文件能不能被访问?我把这种排查思路总结成“三步问”:它在哪个分区、认不认这个分区、这个分区里有没有对应文件。只要把这三步走通,GRUB 层面的大多数问题都能解决。

2.3 内核与 initramfs:为什么启动早期必须有个“临时根文件系统”

内核镜像本身并不包含所有硬件驱动,尤其磁盘控制器、USB 存储这类驱动,往往需要以模块形式加载。这就成了经典的“先有鸡还是先有蛋”问题:内核要挂载根文件系统,可它需要在根文件系统里找驱动模块;可它还没挂载根文件系统,哪里去找驱动呢?

答案是 initramfs,中文常叫“临时根文件系统”。它是一个打包好的微型根目录,里面放了一组必要的工具、驱动模块和初始化脚本。内核启动后会先把这个 initramfs 载入内存并解压,在里面执行 /init 脚本,完成加载驱动、组装 md/dm 设备、挂载真正的根分区等动作,然后 pivot_root 切换到真实系统根目录,把控制权交给 /sbin/init。在当前主流发行版里,这个 init 其实是指向 systemd 的符号链接。

initramfs 的重要性在故障排查中体现得非常明显:如果你压缩内核时缺了某个磁盘驱动,或者 initramfs 文件本身损坏了,系统会卡在一个早期阶段,界面上可能只有几句“Unable to mount root fs”或者直接 kernel panic。好在这类问题通常不需要重装,用系统安装盘或者 live 环境 chroot 进去重新生成一下 initramfs 就能恢复。具体命令是 dracut(红帽系)或 mkinitramfs(Debian/Ubuntu 系),后面会详细说。

2.4 systemd 阶段:PID 1 才是真正的“系统总管”

内核完成挂载根文件系统后,会启动第一个用户空间进程,这个进程的 PID 永远是 1。传统发行版里它是 SysVinit,现在主流发行版几乎全换成了 systemd。systemd 会按依赖关系并行启动各个单元,比如挂载文件系统、启用网络、拉起系统服务,最终到达 multi-user.target 或者 graphical.target,显示登录界面。

systemd 引入的“Target”机制有点类似传统运行级别,但它更灵活。我排查时习惯先看当前默认 target:systemctl get-default,如果机器异常进入 rescue.target 或 emergency.target,说明之前某个环节明确拉了“刹车”。另外 systemd 还负责处理 /etc/fstab 里定义的文件系统挂载,如果 fstab 里写了一个不存在的分区,systemd 会在启动过程中等待很长时间并报错,甚至进入 emergency 模式。这类问题在实战中占比不低,十次启动故障里至少有两三次和 fstab 配置错误有关系。

3. GRUB 引导故障的实战修复:先分清“黑屏”和“命令符”的差别

3.1 三种典型故障形态:grub> 提示符、grub rescue>、直接黑屏

我在处理现场故障时,会先看屏幕信息,因为它直接能帮我缩小排查范围。

第一种是看到 grub>,这说明 GRUB 已经正常加载,只是没找到配置文件或者配置里指定的内核文件路径不对。这种情况下大环境是相对安全的,因为 GRUB 已经拿到了控制权,可以手动输入命令引导。

第二种是看到 grub rescue>,这就麻烦一点,说明 GRUB 连自己的“主程序”都没能完整加载,只加载了第一段代码,而第二段代码所在的路径已经丢失。此时能用的命令非常有限,只有 ls、set、insmod、normal 这些基础命令。修复时需要先搞清楚 /boot 分区的位置和文件系统类型,再用 insmod 加载对应模块,尝试进入正常模式,最后重建 GRUB。

第三种是完全没有 GRUB 界面,开机后直接黑屏或者报“No bootable device”,这基本可以断定是 MBR/EFI 引导区域被覆盖或损坏,或者固件里启动项顺序乱了。这时候只靠手敲命令还不够,我一般会直接从 live CD 或系统安装 U 盘启动,再 chroot 进原系统修复。

3.2 手动引导内核:从 grub> 提示符逃生

假设你运气不错,系统停在 grub> 提示符,而不是 grub rescue>,那可以先尝试手动引导,不急着重建。走过的命令我记在这里:

# 先查看当前 GRUB 能识别哪些分区 ls # 假设识别的分区是 (hd0,msdos1),那就看这个分区里的文件 ls (hd0,msdos1)/

确认 /boot 目录或 / 根目录里的 vmlinuz 和 initramfs 文件在哪个分区之后,就可以手动指定内核和 initramfs,然后启动:

set root=(hd0,msdos1) linux /vmlinuz-3.10.0-1160.el7.x86_64 root=/dev/sda1 initrd /initramfs-3.10.0-1160.el7.x86_64.img boot

这里的 root= 参数指的是真正的根文件系统所在设备,不是 /boot 所在分区,千万别搞混。我见过有人把 root= 写成 /boot 分区设备,结果是内核能启动,但挂根时直接 panic。保险起见,可以用 UUID 代替设备名:root=UUID=xxxx,因为设备名(sda、sdb)在不同环境下可能变化。

等到系统能正常进去之后,第一件事就是重新生成 grub.cfg 并安装引导器,不然下次重启又会掉回老问题。

3.3 重建 GRUB:live 环境下 chroot 五步法

如果 GRUB 已经彻底起不来,只能从外部介质进场。我的标准操作是用一个同版本或相近版本的安装 U 盘,选“试用”或“救援模式”,然后按下面五步走:

# 1. 挂载根分区 mount /dev/sda1 /mnt # 2. 挂载 /boot、/proc、/sys、/dev mount /dev/sda2 /mnt/boot mount --bind /proc /mnt/proc mount --bind /sys /mnt/sys mount --bind /dev /mnt/dev # 3. chroot 进入原系统 chroot /mnt /bin/bash # 4. 重新生成 GRUB 配置 grub2-mkconfig -o /boot/grub2/grub.cfg # 5. 安装引导器到磁盘,BIOS 机器: grub2-install /dev/sda # UEFI 机器则不同,需要先确认 ESP 分区已挂载到 /boot/efi,然后执行: grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg

如果是 Debian/Ubuntu,命令名是 update-grub 和 grub-install,没有后面的 2。还有个小细节:UEFI 模式下一般不需要 grub2-install 指定整个磁盘,而是在系统安装时已经写入了 NVRAM 启动项。如果 NVRAM 里的启动项丢了,还得用 efibootmgr 手动创建:

efibootmgr -c -d /dev/sda -p 1 -L "CentOS" -l \\EFI\\centos\\shimx64.efi

这里 -d /dev/sda 是磁盘,-p 1 是 ESP 分区号。UEFI 启动项的坑在于路径分隔符必须用反斜杠,而且大小写敏感,我踩过好几次。

在开始修复之前有一个原则一定要记住:除非你能确定原系统里没有任何重要数据,否则不要上来就重装。引导损坏不等于系统损坏,数据还在分区里,重建引导的成功率其实极高。

4. 内核启动阶段的故障排查:从 kernel panic 到挂载失败

4.1 kernel panic 不是只能靠重启:看最后几行日志

内核启动阶段的故障往往比 GRUB 故障更让人紧张,因为屏幕上经常出现大段滚屏日志,最后停在一句 Kernel panic - not syncing。这句话本身只表示内核遇到了无法继续处理的致命错误,真正有用的是它前面那段日志里“哪一步失败”。

你说看到 panic 怎么办?按经验,先拍照或者抄下最后那十几行里提到的设备名、UUID、文件系统类型,这是定位的核心线索。panic 的常见来源大概有这么几类:

  • 根文件系统找不到,日志中会有类似 “VFS: Unable to mount root fs on unknown-block” 的话
  • initramfs 损坏或缺失,日志中提示 “Cannot open root device” 或 “Initial RAM disk” 相关问题
  • 内核模块不匹配,比如升级内核后没有同步更新 initramfs
  • 硬件故障,比如磁盘掉线、内存条异常

其中软件层面的问题占大多数,都可以通过修改内核启动参数或重建 initramfs 解决,不需要换硬件。

4.2 用内核参数临时“骗”过故障环节

遇到启动失败,最有效的技巧之一是在 GRUB 界面按 e 键进入编辑模式,在内核命令行末尾追加参数,临时改变启动行为。我常用的参数不少,核心的这几个:

# 进入单用户模式,不启动图形界面和大部分服务 systemd.unit=rescue.target # 跳过 fstab 挂载,避免因错误挂载项卡死 rd.break # 直接执行 /bin/bash,绕开 systemd init=/bin/bash # 指定根设备,防止内核认错分区 root=/dev/sda1

rd.break 这个参数特别有意思,它会让系统在 initramfs 阶段中断,进入一个极简的 shell,让你“看到”initramfs 里的环境。如果在这个 shell 里能看到磁盘设备、能挂载根分区,就说明真正的根文件系统没问题,问题可能出在之后某步;如果连设备都认不到,那就是驱动模块没加载,等于确认了 initramfs 需要重建。

init=/bin/bash 则适合处理那种“内核能启动但 systemd 起不来”的场景。它会把 PID 1 直接替换成一个 bash,让你在极简环境里修复 fstab、日志或服务配置。虽然环境里几乎没什么工具,但 mount、blkid 这些基础命令一般还是能用的。

4.3 重建 initramfs:一个命令的事,重点在选对内核版本

确认要重建 initramfs 后,命令本身很简单:

# 红帽系使用 dracut dracut -f /boot/initramfs-$(uname -r).img $(uname -r) # Debian/Ubuntu 系使用 mkinitramfs mkinitramfs -o /boot/initrd.img-$(uname -r) $(uname -r)

这里 -f 表示覆盖已有文件。重点在于括号里的内核版本号必须和当前使用的 vmlinuz 版本严格一致。有个高频事故场景:系统里有多个内核版本,某个内核更新后对应的 initramfs 生成失败,你在 GRUB 菜单里选了一个旧内核,但它对应的 initramfs 却是新内核的,这就会导致模块不匹配、挂载根分区失败。所以检查时一定要同时确认 vmlinuz、initramfs、/lib/modules/$(uname -r) 三者版本一致。

如果根文件系统是 LVM 或 LUKS 加密的,重建 initramfs 时还要确保 dracut 和 mkinitramfs 能识别出对应的 lvm 或 crypt 模块,不然重建完还是起不来。一般发行版默认都带,但如果你自己精简过内核或手动编译过 dracut 配置,那就要额外注意。

5. systemd 初始化阶段排查:服务起不来、紧急模式、文件系统错误

5.1 先看 target,再查日志:systemd 排错的基本姿势

系统过了内核阶段,就进入了 systemd 的管辖范围。这个阶段出问题,屏幕上的“症状”可能是黑屏、卡在某条日志、或者直接进入 emergency mode。

我的排查顺序是先看现在落在哪个 target:

systemctl get-default systemctl list-units --type=target --state=running

如果默认 target 被改成 rescue.target 或 emergency.target,那不管之前能不能正常起来都会停在这里。这种原因常见于误操作、安装某个软件时修改了默认 target,或者是系统检测到异常主动降级。恢复默认值很简单:

systemctl set-default graphical.target # 服务器一般用多用户模式 systemctl set-default multi-user.target

但如果系统是“想进正常模式却进不去”而被降级,那就要查日志了。systemd 把启动日志也收进 journald,用 journalctl -b 能查看本次启动的全部日志。我实际排查时习惯先看错误级别最高的消息:

journalctl -b -p err

这个命令会打印本次启动中所有 error 级别的日志。如果日志太多,可以结合时间范围过滤:

journalctl --since "2025-01-01 09:00:00" --until "2025-01-01 09:10:00"

5.2 fstab 配置错误与 emergency mode 的处理

生产环境里最常见的 systemd 阶段故障之一,是 /etc/fstab 里写入了错误的分区 UUID 或者不存在的挂载点。systemd 启动时会尝试挂载所有 fstab 条目,遇到失败会等待一段时间,然后报错并进入 emergency mode。

进入 emergency 模式后,先别急着乱挂载,第一步是把根文件系统以读写方式重新挂载:

mount -o remount,rw /

否则你改 fstab 的时候会提示“只读文件系统”。然后查看 fstab 内容:

cat /etc/fstab

找出写错的那一行。你可以用 blkid 查看所有分区真实的 UUID:

blkid

把 fstab 里的 UUID 改成 blkid 输出的正确值,或用注释符号 # 临时禁用掉某一行,保存重启即可。这里特别注意:如果某一行对应的是外部存储设备(比如 USB 移动硬盘),开机时设备没插上也会导致挂载失败。这种场景最好在挂载选项中加 nofail,告诉系统“挂不上就算了,别卡我启动”。

我自己的习惯是,每次改完 fstab 都会用 mount -a 实测一遍,它会把 fstab 里所有未挂载的条目都挂一遍,如果这个命令通过,重启大概率就没问题。

5.3 文件系统损坏与 fsck 修复

启动日志里如果出现 ext4-fs error 或者 Superblock last mount time is in the future 这类话,说明文件系统状态不干净。Linux 在挂载文件系统时如果发现“脏位”被置位,会拒绝挂载或降级为只读。

这时候需要用 fsck 检查并修复。注意:目标分区必须处于未挂载状态,否则会有二次损坏风险。如果你进到了 emergency 或 rescue 环境,先卸载有问题的分区再执行:

umount /dev/sdb1 fsck -y /dev/sdb1

-y 参数表示自动应答“yes”,适合无人值守的大批量修复。如果文件系统损伤特别重,fsck 可能会报 “Superblock is corrupt” 这类信息,这时可以用备份超级块来定位:

mkfs.ext4 -n /dev/sdb1

它会打印出备份超级块的位置,然后使用:

e2fsck -b 32768 /dev/sdb1

把 -b 后面的数字换成备份块位置。日常使用中,只要不是磁盘本身物理损坏,fsck 能救回大部分文件系统问题。

5.4 服务启动失败的定位方法

还有一种故障是系统能进入多用户模式,但业务服务没起来,比如 Nginx、MySQL、Docker 异常。这种“半死不活”的状态,排查起来最考验逻辑。

我一般分三步走。第一步看服务状态:

systemctl status nginx

它会显示服务是否 active、最近日志、PID 信息。第二步看服务依赖链:

systemctl list-dependencies nginx

这能判断是不是某个前置服务没起来导致连锁失败。第三步直接看服务的专属日志:

journalctl -u nginx.service -b

大部分启动失败都是配置语法错误、端口冲突、权限不对这三种原因。比如 Nginx 配置文件里写错了 server_name,nginx -t 就能检查出来;MySQL 起不来,先看数据目录属主属组是否变成了 root;Docker 起不来,先确认 containerd 有没有启动。这类问题不需要重装系统,关键是养成“先查日志,再改配置,最后重启服务”的正确顺序。

6. 排查工具与方法论:把经验沉淀成一套可复用的动作

6.1 启动排查中最好用的几个现场命令

把散落各处的命令整理一下,我平时最依赖的启动排查工具箱大概是这样的:

场景命令说明
查看磁盘分区和 UUIDblkid所有分区的 UUID 和文件系统类型
查看引导配置grub2-mkconfig --version确认 GRUB2 可用;实际测试配置前可以先加 --dry-run
查看内核启动参数cat /proc/cmdline当前启动时实际生效的内核参数
查看启动日志journalctl -b本次启动所有日志
只看错误日志journalctl -b -p err过滤 error 级别以上日志
查看系统默认启动目标systemctl get-default确认是否被改成 rescue
重新生成 GRUB 配置grub2-mkconfig -o /boot/grub2/grub.cfg修改 grub 配置后必须执行
重新生成 initramfsdracut -f 或 mkinitramfs内核模块变更后执行

这些命令不复杂,关键在于“什么时机用哪个”。我的判断逻辑是:屏幕停在哪一阶段,就用那一阶段的命令。如果卡在固件阶段,用 efibootmgr 或检查 BIOS;卡在 GRUB,用 grub2-install 和 grub2-mkconfig;卡在内核,用 dracut 重建 initramfs 或调内核参数;卡在 systemd,用 systemctl 和 journalctl。

6.2 “先备份再动手”和“改动一件事验证一件事”两条铁律

如果你每个月只需要处理一两次引导故障,我的忠告其实很简单:不要同时改多个东西。我见过很多人在 rescue 模式里既重建了 GRUB,又改 fstab,又更新了内核,结果重启后还是失败,完全不知道是哪一步引起的。正确做法是每次只改一个环节,然后重启验证,确认没问题后再进行下一步。

另外就是备份。修改 grub.cfg、fstab 这类关键文件前,先复制一份到旁边,代价几乎为零,回报却极高:

cp /etc/fstab /etc/fstab.bak.$(date +%Y%m%d) cp /boot/grub2/grub.cfg /boot/grub2/grub.cfg.bak

万一改错了,还能快速回滚,不用再来一轮 live 环境折腾。

6.3 我用过的几个偏门但又救过命的技巧

有些细节不见得写在官方文档里,但实测下来真的有用。

第一个,用虚拟机复现和演练。如果你不敢在生产环境练手,完全可以用 VMware 或 VirtualBox 里的虚拟机做实验。把虚拟机的 MBR 弄坏、把 fstab 改错、把内核参数清掉,然后反复练习修复过程,这种模拟训练的肌肉记忆,到真出问题时能救命。

第二个,准备一个常备的启动 U 盘。里面放一个通用发行版的 live 系统,另外把硬件对应的网卡、磁盘驱动也放进去,因为你永远不知道生产环境的存储控制器是什么型号。没有 live 环境,所有修复动作都无从谈起。需要注意的是 U 盘最好做成 UEFI 和 BIOS 双启动兼容,这样新的老的机器都能进。

第三个,手动指定旧的可用内核。当系统因为新内核崩溃时,GRUB 菜单里通常会保留多个内核版本。这种老内核反而是最可靠的“逃生通道”。所以平时看到系统自动更新内核后,旧内核先别急着清理,保留两三个版本对排障很有帮助。

第四个,学会看 journalctl 里的长日志。默认的 systemd 日志是持久化存储在 /var/log/journal 的,但如果某台机器被人清理过日志目录,journalctl -b 就只能看到本次启动的内容,排错线索可能因此断掉。所以有条件的话,把日志持久化配置打开,并定期做日志导出,这也是生产环境的基本功。

6.4 故障排查的“黄金顺序”

最后把我的排查顺序整理成一个固定流程,新人和老手都可以按这个节奏走:

  1. 观察屏幕停留在哪个阶段:固件画面、GRUB 菜单、还是已进入系统
  2. 收集信息:拍摄或记录屏幕最后二十行日志,确认涉及哪些设备和文件
  3. 使用 live 介质进入救援环境,挂载根分区
  4. 先读关键日志,比如 dmesg、journalctl 里的 error 级信息
  5. 判断故障类型:GRUB 损坏、内核参数错误、initramfs 缺失、fstab 问题、文件系统损坏
  6. 逐项修复,每次只改一个点
  7. 重启验证,不行就继续看日志,循环迭代

这套流程看起来基础,却是应对复杂故障最稳的方法论。说白了,排查引导故障没有那么玄学,它就是在“日志”和“配置”之间来回找对应关系,你能看到的信息越多,越不会瞎猜。

说了这么多,我最深的体会就是:永远不要等到机器起不来才开始学引导流程。平时找个测试机,故意把系统搞坏,再去修复,这种“主动找坑”的做法,比我在这儿写一万个字都管用。引导流程不复杂,但它值得你花一晚上好好折腾一遍。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询