
简介《Linux系统启动过程与故障排除》是一份面向Linux系统管理员、运维人员及初学者的实用PDF文档。内容系统梳理了从BIOS自检、MBR引导、GRUB加载到内核启动与系统服务初始化的完整链路并紧扣启动失败场景给出可落地的排查路径。文档重点讲解了GRUB编辑模式下的临时参数调整包括进入single单用户模式、emergency紧急模式、troubleshooting维护模式以及忘记root密码后的init/bin/sh恢复方法同时覆盖GRUB加密配置、/etc/default/grub与grub2-mkconfig的修改流程以及借助troubleshooting模式重新安装GRUB、恢复/boot目录、修正/etc/fstab中UUID错误、还原/etc/passwd等关键文件的具体操作。全篇以步骤化说明为主便于读者按图索骥适合作为日常运维排错的参考手册是系统管理员快速恢复业务的实用指南。压缩包内为单独的PDF文档共1个文件大小225KB已有115人学习轻量易存可随时查阅。1. Linux 系统启动过程与故障排除一份 PDF 背后的实战逻辑看到「Linux 系统启动过程与故障排除.pdf」这个标题很多刚接触 Linux 的运维或嵌入式开发人员会下意识把它当成一本“手册”来读。但实际工作中你会发现真正值钱的不是那几十页流程图而是当你面对一台黑屏、无响应、卡在某个阶段的服务器时能根据启动进度快速定位“卡在哪一步、问题出在哪个子系统”。系统的启动过程是从按下电源键到登录提示符出现的完整链路涉及固件、引导加载程序、内核初始化、systemd 服务编排等多个层次。对运维、嵌入式工程师和自学 Linux 的开发者来说掌握这条链路等于拿到故障排查的路线图——至少能节约一半以上的排障时间。本文不打算复述 PDF 的目录而是按一条可复现的排障路径展开先建立启动链路的整体认知再逐层拆解日志与排查方法最后落到几个高频故障的具体处置手段。2. 启动链路拆解从按下电源键到 systemd 接管每一步都在干什么2.1 固件与引导加载程序BIOS/UEFI 到 GRUB 的交接细节Linux 启动的第一阶段发生在操作系统“看不见”的地方。按下电源键后CPU 首先执行固件代码传统 BIOS 会按照 CMOS 里的启动顺序扫描磁盘而现代 UEFI 固件则会读取 ESPEFI System Partition中的 .efi 引导文件。这里最容易出现的故障是“开机直接进固件设置界面”或“黑屏左上角光标闪烁”前者多是因为启动顺序里没有可引导设备后者常见于 GPT 分区表与 Legacy 引导模式不匹配。GRUB 是 Linux 世界使用最广的引导加载程序它负责加载内核和 initramfs。GRUB 的配置文件通常位于 /boot/grub2/grub.cfgRHEL 系或 /boot/grub/grub.cfgDebian 系但你不应该直接编辑它而是修改 /etc/default/grub 后重新生成。一个常见需求是临时进入单用户模式修改密码此时需要在 GRUB 菜单上按 e 编辑启动项在 linux 那一行末尾追加 rd.breakRHEL/CentOS或 singleDebian/Ubuntu然后按 CtrlX 启动。这个操作经常被新手误用需要特别注意rd.break 是进入 dracut 的紧急 shell此时根文件系统尚未挂载需要手动执行 mount -o remount,rw /sysroot 才能修改密码而不是直接 passwd。2.2 内核初始化与 initramfs为什么启动早期挂载不了根分区内核被 GRUB 加载后首先解压自身并初始化核心子系统包括中断、内存管理、块设备驱动等。但此时内核还没有能力挂载真正的根文件系统——因为根分区所在的磁盘驱动可能是外置存储控制器、NVMe 或者 LVM 逻辑卷这些驱动本身需要从文件系统加载。于是引入了 initramfs初始 RAM 文件系统它是一份打包了必要驱动和启动脚本的小型根文件系统被 GRUB 加载到内存中由内核解压后作为临时根使用。initramfs 的生成工具在 RHEL 系是 dracut在 Debian 系是 mkinitramfs。当你更换了磁盘控制器、修改了根分区类型、或者从 IDE 迁移到 virtio 后系统无法启动大概率就是 initramfs 里缺少对应驱动。这时候需要从救援模式或 LiveCD 启动chroot 到原系统后重新生成 initramfs。以 RHEL 系为例# 挂载原系统根分区到 /mnt并绑定必要的系统目录 mount /dev/sda2 /mnt mount --bind /dev /mnt/dev mount --bind /proc /mnt/proc mount --bind /sys /mnt/sys # chroot 进入原系统 chroot /mnt /bin/bash # 重新生成 initramfs指定当前内核版本 dracut -f /boot/initramfs-$(uname -r).img $(uname -r)这段命令的核心是 dracut -f 强制覆盖生成当前内核版本的 initramfs。uname -r 获取的是 chroot 环境里 /lib/modules 下实际存在的内核版本号如果此版本号对应的模块目录缺失dracut 会报错。在重新生成之前建议先检查 /lib/modules 下目录名和 /boot 下 vmlinuz-* 文件名是否一致。Debian/Ubuntu 系则用 update-initramfs -u -k all 一键更新所有内核的 initramfs无需手动指定版本。2.3 systemd 启动序列如何看懂 Target 依赖而不是背命令内核完成初始化后会执行 initramfs 中的 /init 脚本该脚本最终会把控制权移交给真正的根文件系统上的 /sbin/init。在现代 Linux 发行版中这个 init 通常是 systemd。systemd 的启动过程不是线性的一堆脚本按顺序跑而是一个由 Target 组成的依赖图。默认启动目标在 RHEL 系是 graphical.target图形界面在服务器最小化安装时是 multi-user.target多用户字符界面。排查 systemd 启动慢或卡死的问题不要盯着 /var/log/messages 里的滚动日志而应该用 systemd-analyze 系列命令。systemd-analyze 可以显示内核、initrd 和用户空间各阶段耗时systemd-analyze blame 会列出每个单元启动耗时从大到小排序systemd-analyze critical-chain 显示关键链路上最耗时的单元。这三条命令是定位“开机慢”的黄金组合。例如 critical-chain 输出中显示某个 network-online.target 等了 90 秒那多半是 NetworkManager 在等待 DHCP 超时此时需要调整网络配置让其快速失败或者改为静态 IP。另一个高频场景是服务启动顺序错误导致依赖服务起不来。比如你在某台机器上把 nginx 设置成了开机自启但 nginx 依赖的磁盘挂载点还没就绪最终 nginx 启动失败。此时不要急着 enable 服务先用 systemctl list-dependencies nginx.service 查看它的依赖关系确认它是否 RequiredBy 了正确的 mount 单元。如果确实存在挂载依赖可以在 nginx.service 的 [Unit] 段添加 RequiresMountsFor/data 声明让 systemd 在启动 nginx 前先确保 /data 已完成挂载。3. 启动日志与故障定位在哪看日志、怎么把日志时间对齐到启动阶段3.1 dmesg、journalctl 与 /var/log/boot.log 的职责划分排查启动故障的首要技能是知道每条日志从哪里来。内核日志由 dmesg 或 journalctl -k 查看记录的是从内核解压开始到驱动初始化完成的全过程包括硬件识别、PCI 设备枚举、文件系统挂载等。用户空间日志则由 systemd-journald 收集可以用 journalctl -b 查看本次启动的所有日志-b -1 查看上一次启动的日志这在“当前系统能起来但上次起不来”的场景里尤其有用。/var/log/boot.log 在 systemd 时代已经很少由发行版默认写入很多教程还在教人去 cat 这个文件实际上是过时做法。正确的做法是优先使用 journalctl因为 journald 会把内核日志和用户空间日志统一收集并按时间排序。如果你需要把内核日志和 systemd 日志时间对齐可以分别执行 journalctl -k -b 和 journalctl -u 某个服务 -b通过内核时间戳秒级来对应启动的哪个阶段。3.2 卡住不动时用启动参数让系统告诉你卡在哪当系统卡在黑屏或滚动日志停止时第一反应不应该是重启然后碰运气而是主动给内核传参来暴露问题。在 GRUB 界面按 e 编辑启动项在内核命令行linux 开头的那一行末尾追加两个参数后启动systemd.log_leveldebug 和 systemd.log_targetconsole。这样 systemd 的调试日志会直接输出到控制台你能看到每个单元的启动状态卡在哪个单元一目了然。如果连内核阶段都过不去则追加 nomodeset 参数禁用内核显卡驱动模式设置或 rd.shell 进入 initramfs 的紧急 shell。常见的“黑屏但系统实际活着”的场景多半是显卡驱动如 nouveau与 framebuffer 冲突此时用 nomodeset 启动后再安装专有驱动属于基本操作。另一个参数是 single进入单用户模式跳过大部分服务适合修复因第三方服务导致的循环崩溃。3.3 一个实战案例日志时间轴与硬件驱动的对应分析假设你遇到一台服务器开机非常慢从按电源键到 SSH 可用需要 8 分钟。用 journalctl --list-boots 查看历史启动记录发现上一次启动也是 8 分钟说明不是偶发。再用 systemd-analyze blame 排序发现 dev-sda1.device 耗时 300 秒。于是用 journalctl -b -u dev-sda1.device 查看该设备单元的日志发现内核在反复尝试读取某个扇区并超时进一步 dmesg | grep -i error 看到大量 I/O 错误——这基本可以判断是磁盘坏道或者 SATA 线缆接触不良。整条链路用三条命令就完成了定位而如果只看 /var/log/messages 几乎没法快速建立这种因果。4. 高频启动故障的排查手册8 个你能直接落地的处置手段4.1 现象一开机进入 GRUB 命令行而不是菜单现象系统重启后直接停留在 grub 提示符没有显示菜单。原因grub.cfg 丢失、损坏或者 /boot 分区未被正确识别。解决如果 grub.cfg 只是损坏但内核还在可以在 grub 提示符下手工引导。先执行 ls 列出可用设备找到 /boot 所在分区假设是 (hd0,msdos1)再执行# 在 grub 提示符下手工设置根设备和内核路径 set root(hd0,msdos1) linux /vmlinuz-5.14.0-362.el9.x86_64 root/dev/sda2 initrd /initramfs-5.14.0-362.el9.x86_64.img boot这里的 vmlinuz 和 initramfs 文件名必须和 /boot 目录下实际存在的文件一致可以用 ls /boot 先查看。如果 boot 成功进入系统后立即执行 grub2-mkconfig -o /boot/grub2/grub.cfg 重新生成配置文件否则下次还会卡在 grub 提示符。注意如果你用的不是 RHEL 系而是 Debian/Ubuntu命令是 update-grub。4.2 现象二内核 panic — not syncing: VFS: Unable to mount root fs现象启动过程中出现 VFS: Unable to mount root fs on unknown-block 错误随后内核 panic。原因根分区设备名错误、根文件系统驱动缺失、或 initramfs 内没有对应文件系统模块。解决确认 GRUB 菜单里 root 参数指向的设备真实存在。常见翻车点是使用 /dev/sda1 这样的设备名但系统存在多块磁盘且 BIOS 识别顺序变化导致 sda 变成 sdb。此时 root 应该用 UUID。在 GRUB 菜单按 e 查看 linux 行把 root/dev/sdaX 改为 rootUUIDxxxxUUID 值可以从 grub 命令行用 ls -l /dev/disk/by-uuid 查得。如果确认 UUID 没错但依旧报错则按 2.2 节方法重新生成 initramfs。4.3 现象三启动卡在 A start job is running for /dev/mapper/xxx现象屏幕长时间显示 A start job is running for dev-mapper-xxx.device 并计时直到 90 秒超时后失败。原因systemd 等待某个设备单元超时通常是 LVM 逻辑卷、加密分区或网络块设备未就绪。解决首先确认 /etc/fstab 里是否引用了不存在的设备。常见做法是把 fstab 中的设备名改为 UUID并添加 nofail 选项针对非关键分区这样即使设备缺失也能跳过。命令如下# 查看当前系统所有块设备的 UUID blkid # 修改 fstab 中对应行例如将 # /dev/mapper/data-data /data ext4 defaults 0 2 # 改为 # UUIDxxxx-yyyy-zzzz /data ext4 defaults,nofail 0 2注意不要把根分区的 nofail 加上否则根分区挂载失败时系统会进入 emergency mode 而不是跳过反而掩盖问题。修改 fstab 后执行 systemctl daemon-reload 并重新挂载测试不要直接重启避免改错后起不来。4.4 现象四服务启动顺序导致依赖失败进入 emergency mode现象开机进入 emergency mode提示 Failed to mount /data 或某个服务启动失败。原因systemd 严格按依赖启动但 fstab 或 unit 文件没有声明好挂载关系。解决如果是 fstab 中挂载点依赖可以在对应 systemd 服务里添加 RequiresMountsFor/data这样 systemd 会保证挂载完成后再启动服务。如果只是某次启动中手动挂载导致 fstab 缺失但业务又需要建议用 systemctl edit nginx.service 添加片段而不是直接改 /usr/lib/systemd/system/nginx.service因为更新软件包会覆盖原文件# 创建服务单元的追加配置 systemctl edit nginx.service # 在打开的编辑器中添加 [Unit] RequiresMountsFor/data # 保存后重载配置 systemctl daemon-reload systemctl restart nginx.service这种片段方式的好处是保留原服务文件不动只覆盖新增配置软件包升级也不会丢失你的修改。4.5 现象五开机后启动图形界面黑屏但 SSH 可连现象服务器能远程登录但本地显示器黑屏或花屏GUI 无法显示。原因显卡驱动与内核 framebuffer 冲突。解决先用 SSH 登录检查 nouveau 驱动是否被加载lsmod | grep nouveau如果加载则禁用。在 /etc/modprobe.d/ 下创建 blacklist-nouveau.conf内容为 blacklist nouveau 和 options nouveau modeset0然后重建 initramfs 并重启。如果是笔记本或 NUC 等混合显卡设备可能还需要在内核参数里添加 acpi_osilinux 或 videoLVDS-1:e 来修正显示输出。4.6 现象六密码忘记需要进入单用户模式修改 root 密码现象忘了 root 密码无法登录系统。解决在 GRUB 菜单按 e 编辑找到 linux 行末尾追加 rd.breakCentOS/RHEL 7或 single早期 SysVinit。以 CentOS 9 为例启动后进入 switch_root:/# 提示符执行以下命令# 重新挂载根文件系统为可写 mount -o remount,rw /sysroot # chroot 进入真正的根目录 chroot /sysroot # 修改 root 密码 passwd root # 退出 chroot 并重启 exit reboot -f这里的关键是 mount -o remount,rw /sysroot因为 rd.break 默认以只读方式挂载根文件系统不执行这一步直接 passwd 会报错。修改密码后要确保 SELinux 上下文正确执行 touch /.autorelabel 让系统在下次启动时自动重打 SELinux 标签否则可能因为安全上下文错误导致无法登录。4.7 现象七启动内存不足 OOM 导致内核 panic现象启动过程中内核 panicdmesg 显示 Out of memory。原因内存过小或 initramfs 解压需要的内存超限。解决如果是虚拟机或嵌入式设备检查分配给内核的内存量。可以在启动参数里添加 mem512M 来限制内核可用内存看是否能正常启动以验证是不是内存探测问题。如果确认是 initramfs 太大导致内存不足可以精简 initramfs 内容去掉不必要驱动模块。RHEL 系可以用 dracut --omit-drivers floppy 重新生成减少体积。4.8 现象八重复循环重启或启动即崩溃现象系统启动一段时间后自动重启或反复循环无法进入登录界面。原因硬件不稳定、内核 oops 触发 panic 后自动重启或者系统检测到关键服务失败后主动重启。解决先检查 /proc/sys/kernel/panic 的值如果为 0 则内核 panic 后不会自动重启。如果系统反复重启需要抓 panic 现场。在 GRUB 菜单按 e 编辑在 linux 行末尾添加 panic5 和 oopspanic 参数让 panic 或 oops 后 5 秒重启并记录日志到磁盘。如果无法抓取用串口连接服务器添加 consolettyS0,115200 参数把日志输出到串口这是内核调试的基本方法尤其适用于没有显示器的嵌入式设备或云主机。5. 启动故障排查的 5 个常见误区别再把玄学当经验这里讲的五个误区是我在维护大量 Linux 服务器后总结的血泪经验。第一个误区是“重启能解决一切”。重启前一定要先记录当前状态至少执行 journalctl -b -x 查看本次启动的日志并把关键行拍照或复制下来否则重启后现场丢失只能靠猜。第二个误区是“所有启动慢都看 dmesg”实际上 dmesg 只涵盖内核阶段systemd 用户空间的耗时要用 systemd-analyze blame 来看两者是不同维度。第三个误区是“直接编辑 grub.cfg”这样做很容易在下次 grub2-mkconfig 时被覆盖应该修改 /etc/default/grub 后再生成。第四个误区是“在 fstab 里写死设备名”。我知道很多老工程师习惯写 /dev/sda1但现代机器上磁盘顺序变化太常见一旦 BIOS 识别顺序变化系统直接进 emergency mode。正确的做法是全部使用 UUID用 blkid 获取后再写。第五个误区是“忘记 SELinux 的影响”。当你修改了 /etc/shadow 或系统文件后直接重启如果 SELinux 处于 enforcing 模式可能会出现诡异的“密码正确但登录失败”此时在启动参数里加 enforcing0 验证然后重打标签 regular 解决。这五点看起来简单但每一条我都见过实际生产环境翻车希望你不要再踩。6. 从日志数据到启动性能优化三个能立刻用上的进阶技巧进入正题的最后一步我们聊点能直接提升启动效率和排障能力的手段。第一个技巧是给关键的启动单元添加超时控制。默认 systemd 等待设备和服务的时间是 90 秒对于网络挂载等设备这个时间太短可以给对应 mount 单元设置 TimeoutSec300但对于不需要等待的设备可以缩短到 30 秒避免浪费。第二个技巧是建立启动性能基线。我习惯在系统初始化完成后执行 systemd-analyze /var/log/boot-baseline.txt后续每次改动内核参数或服务再生成一份并 diff能够直观看到哪些改动影响了启动时间。第三个技巧是学会使用 Trace 功能排查服务依赖卡顿。systemd 提供了 systemd-analyze verify 命令可以静态检查 unit 文件的语法和依赖完整性在部署前发现潜在问题。配合 systemctl list-units --statefailed 定期检查失败的单元能提前规避很多故障。如果你管理的机器数量较多建议把所有机器的 journald 日志集中收集到一台日志服务器用 journalctl --merge 或 rsyslog 转发这样即使机器起不来也能从远端查看上一次启动的日志。最后分享一个我自己的习惯每次修改内核启动参数或 fstab 之前先把原文件备份到 /root/boot-backup/ 目录并记录修改时间和原因。这样即使改坏了也能快速回滚而不是手忙脚乱地敲 rescue 命令。启动过程的排查本质上是一项“时间轴对齐”的工作——把固件、内核、initramfs、systemd 四个阶段的日志按时间顺序拼起来问题点会自然浮出水面。希望这篇笔记能帮你在面对 Linux 启动故障时少走弯路让目标系统和日志数据成为你最可靠的排障伙伴。本文还有配套的精品资源点击获取