ARTICLE DETAIL

资讯详情

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

Linux启动过程全解析:从BIOS到systemd的故障排查指南

Linux启动过程全解析:从BIOS到systemd的故障排查指南 简介《Linux系统启动过程与故障排除.pdf》是一份针对系统管理员、运维工程师及备考Linux认证读者的技术笔记全面梳理从BIOS自检、MBR主引导记录、GRUB引导装载到内核加载、systemd服务初始化的完整启动链路并重点标注了各阶段常见故障的定位思路。整个资源打包为单个PDF文件大小约225KB内容紧凑、图文结合适合放在手边随时查阅。已有115人学习下载对启动排错有明确参考价值。文档详细讲解了GRUB配置的正确修改方式指出应编辑/etc/default/grub并运行grub2-mkconfig重新生成配置而不宜直接改动grub.cfg还演示了进入单用户模式和emergency模式的方法并覆盖忘记root密码时采用init/bin/sh临时挂载并重设密码的操作。针对更严重的启动故障则介绍了troubleshooting模式下GRUB重装、/boot目录重建、fstab中UUID修正以及passwd/shadow文件恢复等排错案例可帮助读者建立从现象到根因的完整排错路径是一份实用的速查手册。1. Linux 系统启动过程与故障排除从按下电源到登录界面这中间发生了什么如果你维护过几台 Linux 服务器大概率经历过这种场面明明昨天还好好的今天重启后机器卡在黑屏或者滚了一屏日志就停住不动。这时候手上没有显示器只有一串串看不懂的内核消息很多人第一反应是重装系统——但 Linux 启动过程的每一个阶段都有迹可循绝大多数启动故障都是可以在几分钟内定位的。这套从 BIOS 到 systemd 的启动链路既是排查问题的地图也是理解 Linux 系统管理的基础。本文不打算讲教科书式的理论而是按照一条真实的开机链路把每个阶段做什么、怎么验证、出问题了看哪里以及我踩过的那些坑一次讲清楚。适合刚接手 Linux 服务器运维、或者准备系统集成面试的工程师对照着自己机器走一遍。2. 启动链路全景图固件、引导器、内核与 init 的四级接力2.1 为什么先要分清 BIOS 和 UEFI这决定了你排查故障的入口按下电源键后第一段代码既不是 Linux 的也不是 GRUB 的而是写在主板固件里的。传统 BIOS 和现代 UEFI 的启动流程有本质区别故障表现也完全不同。BIOS 时代固件会扫描第一个可启动磁盘的主引导记录MBR读取前 512 字节里的引导代码而 UEFI 固件会直接读取 ESP 分区EFI System Partition里的 .efi 文件比如 \EFI\ubuntu\shimx64.efi。这意味着同样一个“开机黑屏”在 BIOS 机器上可能是 MBR 损坏在 UEFI 机器上可能是 ESP 分区文件丢失或引导条目失效。判断当前机器用哪种启动方式最简单的方法是查看 /sys/firmware/efi 目录是否存在。存在就是 UEFI不存在就是传统 BIOS。这个区分不是单纯涨知识而是排查故障时第一个要确认的边界。我遇到过一台机器同事反复重装系统都提示“找不到可启动设备”最后发现是 UEFI 里 Boot Mode 被改成了 Legacy而硬盘是 GPT 分区表两者根本不兼容。这类问题如果不先确认固件类型后面再折腾都是白费。2.2 GRUB 阶段菜单、配置文件与内核加载参数固件把控制权交给引导器后GRUB 就成为主角。GRUB 的任务很纯粹找到内核文件 vmlinuz 和 initramfs把它们加载到内存并传递内核启动参数。这个阶段最常见的故障是 GRUB 菜单不出现、或者内核加载一半挂住。GRUB 的配置文件在第一块硬盘上通常是 /boot/grub/grub.cfg但注意不要直接编辑它它是通过 update-grub 或 grub-mkconfig 从 /etc/default/grub 和 /etc/grub.d/ 下的脚本生成的。排查 GRUB 故障前先要理解 GRUB 能做什么。在 GRUB 菜单界面按c进入命令行可以用ls查看磁盘分区用cat查看文件用linux和initrd命令手动加载内核。这套交互式命令是我修复启动问题的主要武器。常见做法是先用ls找到 /boot 所在分区比如(hd0,msdos1)然后试探性查看cat (hd0,msdos1)/boot/grub/grub.cfg。如果文件能读说明分区文件系统基本正常如果读不出来可能是分区号不对也可能是文件系统损坏。2.3 initramfs 到底在忙什么为什么内核不能直接挂载根文件系统很多人以为内核被 GRUB 加载后就直接挂载根分区了实际上中间还隔着一个 initramfs初始 RAM 文件系统。这是因为根文件系统可能位于 LVM 逻辑卷、加密分区或特殊驱动支持的 SSD 上而内核自身不具备这些复杂场景的驱动能力。initramfs 是一个小型根文件系统里面包含了必要的驱动模块和脚本它负责加载这些驱动然后挂载真正的根分区最后通过 switch_root 把控制权交给 /sbin/init。这个阶段出问题时的典型现象是屏幕上闪过Failed to mount /sysroot或者dracut-initqueue timeout之类的错误然后掉进 emergency shell。我第一次遇到时很慌以为是硬盘坏了后来才知道是内核参数里根分区指定错误。查看当前内核参数可以用cat /proc/cmdline如果里面的root指向的 UUID 与你实际的根分区 UUID 不一致就会卡在这里。解决办法是在 GRUB 菜单按e编辑启动项把rootUUIDxxxx改成正确值然后按CtrlX启动。这个操作是临时修改系统起来后记得更新 /etc/default/grub 里的 GRUB_CMDLINE_LINUX再执行 update-grub 永久写入。2.4 systemd 接管从内核态到用户态的最后一棒switch_root 成功之后内核执行 /sbin/init在主流发行版上这个文件是指向 systemd 的软链接。systemd 作为 PID 1 启动接着按依赖关系并行启动各个单元。这里有一个理解启动过程的关键点systemd 不是简单按顺序跑脚本而是根据单元之间的依赖关系构建一个启动事务。默认目标通常是 multi-user.target命令行或 graphical.target图形界面它们又依赖 basic.target、sysinit.target 等。查看启动过程细节最直接的工具是systemd-analyze blame它会按时间列出每个单元启动耗时。再往下钻可以看systemd-analyze critical-chain它显示的是从目标回溯到根节点的关键链。如果某一步卡住通常能在journalctl -b里看到对应的错误信息。这个阶段故障面比较广但多数集中在网络服务等待超时、某个挂载点找不到、或者自定义服务里写了死循环。排查思路是先看启动到哪个单元停住再针对这个单元查日志而不是盲目重启。3. 最小化可复现的启动故障排查路径三个强制阶段3.1 阶段一在 GRUB 菜单里做减法用内核参数隔离故障遇到启动黑屏或卡住我第一件事不是进救援模式而是在 GRUB 菜单按e找到以linux开头的那一行在行尾追加一个关键参数systemd.unitemergency.target。这个参数的意思是让 systemd 跳过所有正常服务直接进入紧急模式——一个只读挂载根文件系统的维护环境。为什么要这么做因为它能把“内核是否能起来”和“用户态服务是否能起来”两个问题彻底分开。如果加了参数后能进入紧急模式的 shell说明内核和根文件系统没问题问题出在某个服务如果还是卡住那就回到前面两个阶段继续查。另一个常用参数是rd.break它让 dracut 在切换到真实根文件系统之前停下来进入一个包含 initramfs 环境的 shell。这个参数适合怀疑是根文件系统或驱动问题时使用。在这个环境里可以手动查看 /dev、/sys 里的设备状态确认内核是否识别了硬盘、网卡等硬件。我曾在一次虚拟机启动故障中用这个参数发现 virtio 驱动没有被 initramfs 包含根因是内核更新后没有重新生成 initramfs用dracut --force重新生成一次就解决了。参数说明systemd.unitemergency.target是 systemd 级别的内核参数可以强制覆盖默认启动目标rd.break是 dracut 的调试参数会在 initramfs 阶段中断。两者都适合临时调试用完就删。还要提醒一点在 GRUB 里按e修改的是当前启动项不会写入磁盘排查阶段不用怕改坏确认有效后再去改配置文件固化。3.2 阶段二chroot 进现有系统修复引导与文件系统如果紧急模式能进但需要修复的是 GRUB 或重置密码那就用 chroot 把现有系统“换根”进去操作。做法是先挂载根分区、/boot 和 /proc、/dev、/sys 这些伪文件系统然后 chroot 进去此时你就拥有了一套完整的系统工具链。具体命令序列如下# 假定根分区是 /dev/sda2先在挂载点下挂载根分区 mkdir -p /mnt/root mount /dev/sda2 /mnt/root # 挂载必要的内核虚拟文件系统 mount --bind /dev /mnt/root/dev mount --bind /proc /mnt/root/proc mount --bind /sys /mnt/root/sys # 如果是独立 /boot 分区单独挂载 mount /dev/sda1 /mnt/root/boot # 换根 chroot /mnt/root /bin/bash逻辑说明mount --bind 会把当前系统的 /dev、/proc、/sys 映射到目标目录让 chroot 环境里的进程能看到内核状态和硬件设备。不能直接跳过这些挂载否则在 chroot 里执行 grub-install 会报错说找不到 /dev。进入 chroot 后先运行mount -a看 /etc/fstab 是否有报错然后有条不紊地检查。常用修复命令是grub-install /dev/sda传统 BIOS或grub-install --targetx86_64-efi --efi-directory/boot/efiUEFI接着执行update-grub重新生成 grub.cfg。这套流程也是重置 root 密码的标准操作。在 chroot 里直接执行passwd root即可不需要知道旧密码。注意如果根文件系统是 LVM要先激活卷组命令是vgchange -ay如果是 LUKS 加密分区需要先cryptsetup luksOpen /dev/sda2 myroot。很多新手在 chroot 这一步卡住就是忘了处理 LVM 和加密这两层。动手之前先确认lsblk -f的输出别盲目按教程敲命令。3.3 阶段三用 journalctl 逆向定位启动失败的单元修复引导之后如果系统能起来但启动速度很慢或者某个服务报错就需要看日志。systemd 把内核日志和用户态服务日志统一收进 journal用journalctl -b查看本次启动的全部日志。但一次性输出几百行人眼很难扫到关键错误。我用的套路是先看启动耗时排名再针对排名靠前的服务看详细日志。# 查看本次启动各单元耗时 systemd-analyze blame # 查看启动关键链 systemd-analyze critical-chain # 查看本次启动中标记为 failed 的单元 systemctl --failed # 单独查看某个服务的启动日志 journalctl -b -u sshd.service --no-pager参数说明-b表示本次启动-u按单元过滤--no-pager避免输出被 less 拦截适合在脚本里用。如果某个服务反复启动失败systemctl status foo.service会给出简要原因配合journalctl -u foo.service -b看上下文。我遇到过最诡异的一个案例是服务起不来但日志里没有任何 error后来发现是它依赖的 socket 文件路径写错了导致 systemd 一直等待。所以看服务失败不能只看那一瞬间要把前后几十行日志读一遍尤其是标着DEPEND或Condition的提示。4. 内核恐慌与文件系统检查让启动故障大白于天下的两个硬骨头4.1 内核恐慌Kernel Panic不是乱码先抓最后一行有效信息当内核遇到无法恢复的错误时会输出 Kernel Panic 并停止。屏幕上常见的是Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)或者Kernel panic - not syncing: attempted to kill init!。这两种情况虽然都叫 panic但排查方向截然相反。第一种是根文件系统挂载失败大概率是驱动问题、initramfs 缺失、或 root 参数错误第二种是用户态 init 进程无法执行可能是 systemd 二进制损坏、文件系统损坏或者 root 分区只读挂载。记录 panic 信息时不要从头看直接从Kernel panic - not syncing:那一行回推。真正的错误原因往往在整个消息块的最后几行。比如unable to mount root fs之前通常有List of all partitions:或者md: autodetecting RAID arrays之类的提示。如果屏幕输出太快抓不到有两个办法一是用串口或 IPMI 控制台截图二是在内核参数里加panic10让内核在 panic 后 10 秒自动重启方便反复调参测试。4.2 fsck 在启动时为什么会被跳过以及如何强制它文件系统的脏标志是启动时最容易被忽略的环节。ext4 文件系统在异常断电或未正常卸载时会留下需要检查的标志但很多发行版默认不会在每次启动时都强跑 fsck而是有概率性检查或依赖关机时的标记。如果根分区出现逻辑坏块启动时会提示Give root password for maintenance或者直接进入 emergency shell这时就要手工跑 fsck。强制检查的正确方式是在 GRUB 编辑内核参数在linux行末尾追加fsck.modeforce fsck.repairyes。这两个是 systemd 的 fsck 服务参数。fsck.modeforce 表示无视文件系统状态强制全面检查fsck.repairyes 表示自动修复发现的问题。注意如果文件系统损坏严重自动修复可能会丢数据所以跑之前如果有条件先做镜像备份。没有物理备份条件的话至少要记下报错块号并在修复后查一遍 dmesg。修复命令可以单独跑# 卸载根分区后检查注意不要跳过 -f 参数 umount /dev/sda2 fsck.ext4 -f -y /dev/sda2参数说明-f是强制检查即使文件系统标记为干净-y是对所有询问自动回答 yes。这在无人值守场景下很实用但也要承担自动决策的风险。如果 fsck 报告大量块错误修复完后建议看一眼 smartctl 的健康状态因为物理坏道通常是磁盘老化先兆单纯靠 fsck 只是治标。4.3 救援模式与 LiveCD 的选择什么时候用哪种启动彻底起不来GRUB 也进不去或者引导器损坏这时不要继续在故障机上折腾拿出 LiveCD 或 USB 启动盘才是正确做法。LiveCD 环境自带完整工具链可以把故障盘挂载到 /mnt 下再用前面 chroot 的方式修复。这里有个选择问题救援模式能进就用救援模式因为它是从当前系统 initramfs 启动的驱动和内核版本与故障系统一致LiveCD 环境的内核版本可能差很多操作 LVM 或特殊文件系统时反而要多装软件包。我一般先用 U 盘做一个多发行版兼容的启动介质像 SystemRescue 这类工具盘自带大量文件系统工具比手工做 LiveUSB 省事。但注意不要依赖 LiveCD 去修复所有问题有些情况下驱动不匹配会导致 LiveCD 里根本看不到故障盘的设备节点。此时优先考虑进入 initramfs 的 shell也就是加rd.break参数那个环境里至少能保证有正确的存储栈驱动。5. 避坑指南这些启动故障的套路全踩过一遍才算入门5.1 现象更新内核后启动黑屏只有光标闪烁。原因initramfs 没有同步更新很多人执行apt upgrade或dnf update后直接重启结果卡在 GRUB 加载完内核后一动不动。这个坑的根源是内核更新后/boot 里的 vmlinuz 换了新版本但 initramfs 还是旧的或者根本没有生成。老一代的启动脚本会打包 initramfs但如果你用的是自定义内核或者手动管理 /boot这步就容易漏。解决方式在 GRUB 菜单里选择旧版本内核尝试启动能起来就执行dracut --force或update-initramfs -u重新生成当期内核的 initramfs如果连旧内核也起不来就进救援模式重建 initramfs。5.2 现象启动卡在 “A start job is running for /dev/sdb1”。原因fstab 里的挂载项指向不存在的设备这是新手最容易撞上的问题。系统启动时 systemd 会等待某个分区出现但设备可能因为 U 盘拔掉、或者磁盘顺序改变而消失于是等待超时默认 90 秒才继续。解决思路是先确认 fstab 里那些挂载项哪些不是系统必需的把不需要的注释掉。具体做法是启动时加systemd.unitemergency.target进系统编辑 /etc/fstab注释掉可疑的 UUID 条目然后 reboot。更稳妥的办法是挂载时使用nofail选项这样设备不存在也不会阻塞启动。5.3 现象GRUB 菜单找不到直接进救援 shell。原因grub.cfg 被误删或 ESP 分区文件损坏这种故障通常发生在手动清理 /boot 目录的时候。grub.cfg 是生成的删掉之后系统不会自动重建除非你运行 update-grub。如果连 grub.cfg 都不存在GRUB 会掉入grub命令行。解决办法是先用ls确认分区手动按下面流程加载内核和 initramfs# 在 grub 命令行界面执行 set root(hd0,msdos1) linux /vmlinuz-5.15.0-91-generic root/dev/sda2 initrd /initrd.img-5.15.0-91-generic boot这个方法是临时的能进去系统后立刻执行 update-grub 生成新配置。为了防止以后再发生重要的配置文件最好备份或者不要手动删 /boot 里的东西。5.4 现象开机直接进入 emergency mode提示 “Failed to mount /boot/efi”。原因EFI 分区文件系统损坏或类型错误UEFI 启动的机器最常见的就是 ESP 分区挂载失败。可能是 ESP 分区被格式化成了 ext4而 UEFI 固件只能读 FAT 系列也可能是分区类型标识不是 EFI System Partition。解决方法是确认分区类型和文件系统是否正确。在 LiveCD 环境里用 gdisk 查看分区类型 GUID应该是c12a7328-f81f-11d2-ba4b-00a0c93ec93b。如果文件系统不对备份文件后格式化为 vfat再重建引导。5.5 现象系统很久才出现登录界面systemd-analyze 显示 network 等待 70 秒。原因DHCP 超时或无网络设备服务器固定 IP 的机器很少见多是 DHCP 客户端在等待地址时卡住。查看systemctl status systemd-networkd-wait-online.service如果状态异常可以考虑禁用该服务或者修改/etc/systemd/system/network-online.target.wants/下链接。更简单的做法是给网络配置里加[Network] DHCPyes和[Link] RequiredForOnlineno这样的参数但具体写法因 NetworkManager 和 systemd-networkd 而异。这个坑的本质是 systemd 认为网络就绪才继续而网络就绪的标准可以配置。6. 用 GRUB 的 savedefault 和自定义脚本做双系统默认项切换顺手验证你的修复平时排查启动故障积累下来的一个实用技巧是操作 GRUB 的默认启动项与 savedefault 配合。如果你机器上装了双系统或者有多个内核版本可以通过/etc/default/grub里的 GRUB_DEFAULT 设置默认项。但我更推荐用grub-set-default搭配GRUB_DEFAULTsaved这样每次启动后下一次默认项由上次启动选择决定。这在回滚内核版本时特别有用你先选择旧内核启动系统会自动记住下次重启还是旧内核而不是非要手动在菜单里选。操作方法是编辑 /etc/default/grub 文件# /etc/default/grub GRUB_DEFAULTsaved GRUB_SAVEDEFAULTtrue GRUB_TIMEOUT5然后执行update-grub生成新配置。这里的 GRUB_SAVEDEFAULTtrue 会让 GRUB 在每次启动时把当前选择的项保存为下一次默认项。如果你需要固定到某个特定内核比如GRUB_DEFAULTAdvanced options for UbuntuUbuntu, with Linux 5.15.0-91-generic注意字符串要精确匹配 menuentry 的标题。我建议直接运行grep menuentry /boot/grub/grub.cfg查看当前实际的菜单项名称别靠记忆去写。验证你的修复是否完整除了能正常登录还可以养成一个习惯每次解决完启动问题后执行一次journalctl -b -p err查看本次启动是否有内核或系统级的错误残留。如果输出为空说明启动链路基本干净。再执行一次systemd-analyze blame | head -10记录一下哪些服务耗时最多便于下次对比。别小看这两个命令它们能帮你把一次“修好了”变成带依据的“确认修好了”。最后说个我自己的习惯遇到任何启动问题先别急着动手用手机拍下屏幕上的完整报错特别是内核 panic 和 grub 提示。之后所有操作都围绕这几行文字展开。很多翻车都是因为看到一半就凭印象敲命令最后越修越乱。系统启动这条链路虽然长但每一段都有明确的验证手段按图索骥总能把你带到问题真正的藏身之处。希望帮到你。本文还有配套的精品资源点击获取
返回列表