ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Linux系统引导流程详解:从BIOS到systemd的启动故障排查指南

Linux系统引导流程详解:从BIOS到systemd的启动故障排查指南 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 PartitionESP其中存放着引导加载器的 .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红帽系或 mkinitramfsDebian/Ubuntu 系后面会详细说。2.4 systemd 阶段PID 1 才是真正的“系统总管”内核完成挂载根文件系统后会启动第一个用户空间进程这个进程的 PID 永远是 1。传统发行版里它是 SysVinit现在主流发行版几乎全换成了 systemd。systemd 会按依赖关系并行启动各个单元比如挂载文件系统、启用网络、拉起系统服务最终到达 multi-user.target 或者 graphical.target显示登录界面。systemd 引入的“Target”机制有点类似传统运行级别但它更灵活。我排查时习惯先看当前默认 targetsystemctl 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 代替设备名rootUUIDxxxx因为设备名sda、sdb在不同环境下可能变化。等到系统能正常进去之后第一件事就是重新生成 grub.cfg 并安装引导器不然下次重启又会掉回老问题。3.3 重建 GRUBlive 环境下 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.unitrescue.target # 跳过 fstab 挂载避免因错误挂载项卡死 rd.break # 直接执行 /bin/bash绕开 systemd init/bin/bash # 指定根设备防止内核认错分区 root/dev/sda1rd.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。我的排查顺序是先看现在落在哪个 targetsystemctl get-default systemctl list-units --typetarget --staterunning如果默认 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:005.2 fstab 配置错误与 emergency mode 的处理生产环境里最常见的 systemd 阶段故障之一是 /etc/fstab 里写入了错误的分区 UUID 或者不存在的挂载点。systemd 启动时会尝试挂载所有 fstab 条目遇到失败会等待一段时间然后报错并进入 emergency mode。进入 emergency 模式后先别急着乱挂载第一步是把根文件系统以读写方式重新挂载mount -o remount,rw /否则你改 fstab 的时候会提示“只读文件系统”。然后查看 fstab 内容cat /etc/fstab找出写错的那一行。你可以用 blkid 查看所有分区真实的 UUIDblkid把 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_namenginx -t 就能检查出来MySQL 起不来先看数据目录属主属组是否变成了 rootDocker 起不来先确认 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 故障排查的“黄金顺序”最后把我的排查顺序整理成一个固定流程新人和老手都可以按这个节奏走观察屏幕停留在哪个阶段固件画面、GRUB 菜单、还是已进入系统收集信息拍摄或记录屏幕最后二十行日志确认涉及哪些设备和文件使用 live 介质进入救援环境挂载根分区先读关键日志比如 dmesg、journalctl 里的 error 级信息判断故障类型GRUB 损坏、内核参数错误、initramfs 缺失、fstab 问题、文件系统损坏逐项修复每次只改一个点重启验证不行就继续看日志循环迭代这套流程看起来基础却是应对复杂故障最稳的方法论。说白了排查引导故障没有那么玄学它就是在“日志”和“配置”之间来回找对应关系你能看到的信息越多越不会瞎猜。说了这么多我最深的体会就是永远不要等到机器起不来才开始学引导流程。平时找个测试机故意把系统搞坏再去修复这种“主动找坑”的做法比我在这儿写一万个字都管用。引导流程不复杂但它值得你花一晚上好好折腾一遍。
返回列表