news 2026/9/9 3:50:46

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux启动过程全解析:从BIOS到systemd的排障指南

1. 启动过程这东西,值得你专门花一章来啃

RH134的第十章“控制启动过程”,在整门课里的地位有点像驾照考试里的科目二——平时看着不起眼,真到了故障现场,救急全靠它。前面几章教你装系统、管存储、配网络,这章讲的是系统从按下电源键到出现登录提示符之间,到底发生了什么,以及当这个过程出问题时,你能从哪里插手。

我学这一章时最大的感受是:启动过程不是一条直线,而是一条有多个“岔路口”的管道。每个岔路口都留了检修口,也就是各种启动参数和救援模式。你要做的不是背下每个开关的位置,而是搞懂每个检修口什么时候能打开、打开之后能干什么、干完怎么出来。

很多同学容易把这章当成命令背诵题,systemctl isolate rescue.target背得滚瓜烂熟,但真问他rescue模式和emergency模式差在哪、什么时候用哪个,就答不上来了。这恰恰是RHCSA考试和实际工作中最喜欢考察的点。

这一章适合谁看?正在备考RHCSA/RH134的朋友、刚入职需要维护Linux服务器的初级运维、还有那些一直靠重启解决一切问题的“重启侠”——学会控制启动过程之后,很多问题不用重启也能处理,真需要重启的时候,也能在重启过程中做点手脚。

2. 先搞懂启动链条:从按下电源键到登录提示符之间发生了什么

2.1 固件阶段:BIOS和UEFI各自怎么找启动设备

任何Linux系统启动,第一步都不是Linux自己说了算,而是固件先接管。老一点的机器用BIOS,新机器基本都是UEFI。这个阶段的核心任务就一件事:找到一个包含引导加载程序的设备

BIOS的方式很“机械”——它按照CMOS里设置的启动顺序,逐个检查硬盘、光驱、U盘,在每个设备的前512字节(MBR区域)寻找可用的引导代码。这个区域太小了,装不下复杂逻辑,所以BIOS年代的GRUB会把自身拆成好几段,MBR里只放第一段,剩下的存在后续扇区里,每次启动时现场拼接。这也是为什么BIOS时代引导程序损坏后恢复比较麻烦。

UEFI就聪明得多。它直接读取ESP分区(EFI System Partition,一般格式化为FAT32,挂载在/boot/efi)里的.efi引导文件。系统里装了几个操作系统,ESP分区里就有几个对应的.efi文件,UEFI固件通过NVRAM里的启动项记录来调用它们。这个设计的好处是引导加载程序不再受512字节限制,坏了一个可以通过efibootmgr重建启动项,比BIOS时代灵活很多。

RHEL 9默认使用UEFI启动,但RH134的教材并没有放弃对BIOS/传统模式的讲解,原因很简单:生产环境中老机器存量依然很大,而且考试环境也可能会用传统BIOS模式模拟,所以两种固件的差异你得有概念。

2.2 引导加载程序:GRUB2加载内核和initramfs

固件找到GRUB2之后,控制权交给GRUB。RHEL 9用的是GRUB2,配置主文件是/boot/grub2/grub.cfg(BIOS模式)或/boot/efi/EFI/redhat/grub.cfg(UEFI模式)。注意这个文件是生成出来的,不是手写的,手动改完/etc/default/grub之后要执行grub2-mkconfig -o /boot/grub2/grub.cfg重新生成。

GRUB2做的事情分两步:

  • 加载内核vmlinuz-$(uname -r)到内存
  • 加载initramfs(初始RAM磁盘文件系统)到内存

这里我多说两句initramfs。很多初学者不理解:为什么内核不能直接挂载根分区,非得先加载一个临时的RAM文件系统?

原因是内核刚启动时,它还没有能力读取真正的根文件系统。现代服务器用的是各种存储控制器驱动(比如NVMe、SAS HBA卡),这些驱动是编译成模块的,不在内核本体里。内核需要先启动一个迷你的用户空间环境(也就是initramfs),在这个环境里加载必要的存储驱动、识别磁盘、组装LVM或RAID设备,然后才能真正挂载根分区。initramfs本质上是内核和根文件系统之间的桥梁。

还有一个容易忽略的细节:/boot目录下的文件并非全都能直接读。initramfs里包含了/etc/fstab的内容和必要的设备映射信息,所以即使根分区在LVM逻辑卷上,内核也能通过initramfs里的配置找到它。如果你把根文件系统的设备类型改了(比如从LVM改成标准分区),但没有重建initramfs,系统启动时就会卡在“无法找到根设备”的地方——

Warning: /dev/mapper/rhel-root does not exist

这时候你知道大概率是initramfs里的设备信息过期了,用安装光盘进救援模式执行dracut --force重建,就比无头苍蝇一样乱试强得多。

2.3 内核初始化与systemd接管

内核把initramfs里的/init跑起来之后,这个程序会做几件事:加载存储驱动、udev创建设备节点、发现根文件系统并挂载、最后把控制权交给真正的/sbin/init——在现代RHEL里,它就是指向systemd的符号链接。

从这一刻起,启动流程从“内核主导”切换为“systemd主导”。systemd的第一个进程PID永远是1,后续所有用户态进程都是它直接或间接拉起来的。你可以观察到,系统里除了内核线程(PID 2的kthreadd及其子孙),其余所有进程的PPID最终都能追溯到1,这正好验证了systemd的进程树根节点地位。

systemd的启动逻辑不是“按数字顺序执行一堆脚本”,而是按依赖关系并行启动单元。它读取默认目标(default target)对应的依赖树,把能同时启动的服务并行拉起,不能并行的就等前面的完成后立刻启动。这也是RHEL 7之后启动速度明显快于SysVInit时代的原因——SysVInit是严格串行的,服务越多,启动越慢。

3. 启动目标与systemd的关系:rescue、emergency、multi-user到底怎么选

3.1 systemd.target是什么:它不是运行级别,但可以看成一个“状态集合”

老Linux用户都习惯说“runlevel 3”“runlevel 5”,到了systemd时代,这个概念被替换成了target。一个target不是一个孤立的“级别”,而是一个依赖集合——它声明了自己需要哪些单元处于活动状态,systemd会根据这些依赖把整棵依赖树拉起来。

RHEL 9里和启动过程强相关的target有这几个:

Target对应旧runlevel说明
poweroff.target0关机
rescue.target1单用户模式,挂载所有本地文件系统,启动最小化服务
emergency.targetS紧急模式,几乎不启动任何服务,文件系统只读
multi-user.target3多用户字符界面
graphical.target5多用户图形界面
reboot.target6重启

这些target之间是可以互相切换的,并不是系统启动那一刻定的就一成不变。系统运行时,你执行systemctl isolate rescue.target就能切到救援模式;从救援模式里执行systemctl isolate multi-user.target就能切回来。

3.2 修改默认启动目标:set-default和get-default

RHEL 9装机时如果选了带GUI的软件包组,默认target就是graphical.target。很多服务器其实不需要图形界面,为了省内存和安全,可以把默认target改成multi-user.target:

# 查看当前默认 systemctl get-default # 设置为多用户模式 systemctl set-default multi-user.target # 验证 systemctl get-default

注意set-default只是改默认配置,不会立刻切换当前运行状态。想要立即切换使用systemctl isolate multi-user.target

这招在日常运维里太常用了。我处理过一台内存只有2G的旧服务器,装了GNOME桌面,平时根本没人登录图形界面,桌面进程却白白吃掉几百MB内存。改成multi-user.target重启之后,内存占用直接降了一大截,ssh登录速度都快了。

3.3 rescue和emergency:哪个更“急救”

这两个模式是启动排障的核心工具,我分开细说。

rescue.target,救援模式。这个模式下systemd会完成基本初始化,挂载所有本地文件系统(你/etc/fstab里配置的挂载点都会挂上),启动网络(如果配置了的话),然后给你一个root shell。它适合的场景是:系统能启动到一定程度,但某个关键服务起不来导致进不了全功能状态,或者需要修改某个配置文件但文件系统是可读写的。

进入rescue模式的方式:

# 运行中直接切换 systemctl isolate rescue.target # 或者重启时在GRUB菜单按e,在linux行末尾添加systemd.unit=rescue.target

emergency.target,紧急模式。它更进一步,只挂载根文件系统(而且默认是只读的),不启动网络,连服务管理都不初始化。适合的场景是:文件系统损坏需要fsck、/etc/fstab写错导致启动卡住、某些关键系统文件被改坏需要修复。

进入emergency模式的方式:

systemctl isolate emergency.target # 或者在GRUB里添加systemd.unit=emergency.target

这里有个重要的实操细节:emergency模式下根文件系统是只读的,你需要先重新挂载为读写才能修改文件:

mount -o remount,rw /

很多新手进了emergency模式,明明看到了root shell,却执行不了vi /etc/fstab,因为文件系统只读,vi会报错说只读文件系统。先执行上面这条命令,问题就解决了。

两者选哪个?我的经验法则是:如果你怀疑文件系统或基础配置坏了,用emergency;如果只是某个服务或网络的问题,用rescue就够。rescue模式像带着工具箱进了机房,emergency模式像是只带了一把撬棍——越往后者,能干的活越少,但越适合在最恶劣的环境里救命。

4. 系统启动排障:从GRUB菜单到登录提示符,每一环都可能出问题

4.1 内核启动参数:写错一个参数,系统可能直接卡死

控制启动过程的一个重要手段是通过GRUB向内核传递参数。在GRUB菜单界面按e进入编辑模式,找到以linux开头的那一行(RHEL 8/9上可能是linuxefi),在行尾追加参数,然后按Ctrl+x启动。

常用的内核参数我列一下:

  • systemd.unit=rescue.target:直接启动到救援模式
  • systemd.unit=emergency.target:直接启动到紧急模式
  • rd.break:在initramfs阶段中断,进入dracut shell
  • quiet:内核启动时少打印信息(出问题排查时要删掉这个参数)
  • rhgb:Red Hat图形启动画面(排查问题时建议删除)

举个例子。系统开机卡在黑屏但没完全死机,你按e进GRUB编辑,把quiet rhgb两个参数去掉,按Ctrl+x重新启动。这时你能看到内核启动时一行行刷屏的输出,屏幕卡在哪一行,往往就是问题线索所在。

我在实际工作中遇到过卡在Starting Login Service...的情况,看起来像是systemd的登录服务起不来,去掉quiet rhgb后才发现是磁盘I/O错误反复重试导致的。这个线索如果不看启动日志,光靠猜很难定位。

4.2 查看启动日志:journalctl不是只能看当前系统

排障时需要看启动日志,journalctl是主力工具:

# 查看本次启动日志 journalctl -b # 查看上一次启动日志 journalctl -b -1 # 实时跟踪启动日志 journalctl -f # 查看启动耗时排行 systemd-analyze blame

systemd-analyze blame是一个很容易被忽略的好用命令。它列出每个服务启动花了多少时间,按从长到短排序。排查“开机慢”问题时,用这个命令一眼就能看到是哪个服务在拖后腿,我之前遇到过一个Docker服务每次启动要等60秒超时的案例,就是靠这个命令快速定位的。

4.3 GRUB菜单坏了怎么办:从安装介质引导rescue模式

如果你改坏了GRUB配置,或者写错了内核参数导致系统根本进不了GRUB菜单,这时候还有一个终极入口:用RHEL安装光盘/U盘启动,进入rescue模式

在安装介质启动菜单里选择“Troubleshooting”→“Rescue a Red Hat Enterprise Linux system”,系统会扫描现有安装,然后给你三个选项:

  1. Continue:自动探测并把现有系统挂载到/mnt/sysimage
  2. Read-Only mount:只读挂载
  3. Skip:不挂载,直接给shell

选1之后执行chroot /mnt/sysimage,你就进入了原系统的环境,此时可以重新生成GRUB配置、修改fstab、重建initramfs,想干嘛就干嘛。

这里有个经验之谈:进入rescue模式后先看/etc/fstab/boot/grub2/grub.cfg这两个文件的修改时间和内容,十次启动故障有八次是这两个文件被人为改错了。先看它们能省很多排查时间。

5. 单用户模式的实际应用:重置root密码

5.1 rd.break:在initramfs阶段动手

RH134教材里重置root密码的官方推荐方法是rd.break。原理是在内核启动到initramfs阶段时强制中断,跳到一个dracut shell里。这时候真正的根文件系统还没挂载,但你可以在这个阶段做手脚。

具体步骤:

  1. 重启系统,在GRUB菜单按e编辑
  2. 找到linux那一行,在行尾追加rd.break,按Ctrl+x启动
  3. 系统会卡在类似switch_root:/#的提示符
  4. 执行mount -o remount,rw /sysroot(把根文件系统以读写方式重新挂载)
  5. 执行chroot /sysroot切换进真正的根环境
  6. 执行passwd root重置密码
  7. 如果之前启用过SELinux,执行touch /.autorelabel(让下次启动时自动重新打SELinux标签)
  8. 执行exit退出chroot,再执行exitreboot -f重启

注意第7步,RD.break方法会绕过SELinux的进程标签设置,如果直接重启,系统可能因为SELinux上下文不正确而拒绝root登录。加了/.autorelabel之后,重启过程中SELinux会重新标记整个文件系统,虽然耗时稍长,但能避免诡异的权限问题。

5.2 resuce模式重置密码的替代思路

rd.break不是唯一的路子。用前面说的安装介质救援模式也可以,流程类似:进rescue shell、chroot /mnt/sysimagepasswd rootexit、重启。

还有一个思路值得提一下:如果你手上正好有另一台能登录这台机器的方式(比如KVM/vSphere控制台还在,只是忘了SSH密码),其实不用物理重启也能改密码——登录进单用户模式或直接用有sudo权限的账户执行sudo passwd root就行。但真实场景往往是你只有被锁在门外这一个选项,所以rd.break还是必须掌握的。

5.3 重置密码之后:SELinux上下文必须处理

谈到SELinux,我多叮嘱一句。

在很多人的实际测试里,直接rd.break重置密码后重启,系统会提示autorelabel就成功了。但如果你跳过了touch /.autorelabel这步,或者机器上有大量文件需要重打标签(比如数据库数据目录),重启后你可能会被卡在一个SELinux拒绝访问的坑里。

我踩过一次这样的坑:帮客户的物理服务器重设root密码,图省事跳过了autorelabel,结果重启后root登录直接被SELinux拒绝(?)。当时我一脸懵,后来用安装介质进救援模式执行touch /.autorelabel才解决。密码重置本身不难,难的是重置之后系统还能不能正常起来,这一课我一直记到现在。

6. 实际排障复盘:一台RHEL 9机器卡在启动阶段的全过程

理论讲了这么多,我拿一个真实排障案例做复盘,把整个排查链路走一遍,这样知识才能串起来。

6.1 故障现象

一台RHEL 9虚拟机,配置了LVM根分区,某天管理员在/etc/fstab里加了一个额外的XFS磁盘挂载条目,结果重启时系统卡在类似这样的位置:

[ OK ] Found device /dev/mapper/rhel-root. [ OK ] Reached target Initrd Root File System. [ OK ] Reached target Initrd File Systems. Mounting /sysroot...

屏幕停在这里,不再往下走,但也不是完全死机,键盘还能响应。

6.2 排查思路

这种卡在挂载根文件系统前后的情况,八成是initramfs阶段就出问题了。我先在GRUB菜单按e,删掉quiet rhgb重启,观察详细输出,果然看到内核在等待某个设备超时:

Job dev-mapper-rhel\x2droot.device/start timed out.

但我确认过根分区本身没坏。再一想,/etc/fstab里新加的那个XFS挂载条目,可能让systemd误以为根文件系统依赖它——因为fstab里的挂载顺序和依赖关系错误会导致启动任务无限等待。

6.3 解决过程

  1. 重启进入GRUB编辑,添加systemd.unit=emergency.target,跳过所有fstab挂载,直接进emergency模式
  2. 进emergency模式后,先mount -o remount,rw /把根文件系统改为可写
  3. vi打开/etc/fstab,注释掉新加的那行
  4. mount -a测试所有挂载点能否正常挂载
  5. 确认无误后执行reboot

系统恢复正常。整个过程没有用到安装介质,靠的就是在GRUB阶段向内核传递systemd.unit=emergency.target这个参数。

这个案例的教训是:改fstab之前一定要用mount -a做dry-run测试,或者至少确认挂载点目录已存在。我当时是没先建挂载点目录,导致systemd认为该挂载永远失败,从而阻塞了依赖它的所有后续单元。

7. 把这章内容真正变成自己的:几条实操建议

控制启动过程这章,光看书做题是学不踏实的,它是一门“动手技能”。我建议你有条件的话,在虚拟机里把这些实验做一遍:

最基础的一组实验是启动目标切换——把一个运行中的系统从multi-user切到graphical,再切回来,体会一下isolateset-default的差异。

第二组实验是启动参数传递。在GRUB菜单里删掉quiet rhgb,观察启动输出的详细程度差异;追加systemd.unit=rescue.targetemergency.target,分别体验两种模式里的环境差异——文件系统是否只读、网络是否可用、哪些服务在跑。

第三组实验是密码重置。在虚拟机里按rd.break的流程完整走一遍,包括touch /.autorelabel的步骤,然后把重置后的系统重启观察SELinux的relabel过程。做过一遍之后,你就知道为什么这个步骤不能省。

第四组实验是破坏和修复。故意改坏一个服务的配置(比如把nginx的配置改成语法错误),或者往fstab里加一个错误的条目,然后重启,体会启动卡住时排查的完整过程。修复之后再想想:如果连这个服务都起不来,我还能用什么方式进入系统?

这组实验做完,你对启动过程的理解会有一个质的飞跃。到时候再回头看systemctl list-units --type=target的输出,你看到的就不是一串名字,而是一张张可以按需切换的状态网络图。

启动过程就像一栋楼的消防通道——平时没人走,但真出事的时候能不能快速找到入口、顺利到达想去的地方,全靠平时对路线的熟悉程度。RH134这章教的就是这条消防通道的每一道门、每一个转弯、每一个应急开关。把这张地图刻在脑子里,比多记几条命令值钱得多。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 3:50:42

风光储互补微电网Simulink建模与仿真全流程解析

“基于风光储互补微电网建模与仿真分析”这类题目,我在实际辅导和项目评审里见得太多了。很多同学或者刚入行的工程师,一上来就打开Simulink,拖几个光伏、风机、电池的现成模块,连起来跑一下,看到波形出来了就以为大功…

作者头像 李华
网站建设 2026/9/9 3:49:43

数字员工与SaaW:从RPA到智能自动化,企业数字化转型的下一站

1. 全景扫描:数字员工与 SaaW 的底层逻辑转换过去两年我一直在跟踪企业数字化落地项目,一个很明显的感受是:大家聊的已经不是"上不上系统",而是"系统能不能自己干活"。这种转变背后,正是数字员工从…

作者头像 李华
网站建设 2026/9/9 3:47:29

CCSwitch:一个命令秒切AI服务配置,告别多模型配置地狱

做 AI 编码调优这段时间,我电脑里的配置文件几乎快成了重灾区。今天用 Codex 接 OpenAI 官方模型,明天想试试 DeepSeek 的推理能力,后天项目要求切到千问,每次切换都要改一遍 config.toml、换环境变量、重启终端,稍不留…

作者头像 李华
网站建设 2026/9/9 3:46:40

AI编程工具选型指南:TRAE、Cursor、Copilot与通义灵码深度对比

1. 这不是选工具,是选你的编程工作流底座“个人AI编程工具怎么选:免费与付费方案各自适合谁”——这句话背后藏着的,根本不是软件下载链接或价格对比表,而是一个程序员每天要面对的真实生存问题:你写代码的方式&#x…

作者头像 李华
网站建设 2026/9/9 3:45:50

拆解XFCN PZ254V-11-04P:2.54mm排针选型与焊接实操指南

一块被无数人忽视的板级基石:拆解XFCN神火 PZ254V-11-04P 2.54mm排针的选择逻辑与实操要领 做硬件这么多年,我有一个体会:越不起眼的元件,越能决定一块板子的生死。你精心设计的电源网络、高速信号线、精密阻抗匹配,最…

作者头像 李华
网站建设 2026/9/9 3:44:28

西门子PLC采购与选型的全生命周期成本陷阱

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华