ARTICLE DETAIL

资讯详情

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

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

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.cfgBIOS模式或/boot/efi/EFI/redhat/grub.cfgUEFI模式。注意这个文件是生成出来的不是手写的手动改完/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-defaultRHEL 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.unitrescue.targetemergency.target紧急模式。它更进一步只挂载根文件系统而且默认是只读的不启动网络连服务管理都不初始化。适合的场景是文件系统损坏需要fsck、/etc/fstab写错导致启动卡住、某些关键系统文件被改坏需要修复。进入emergency模式的方式systemctl isolate emergency.target # 或者在GRUB里添加systemd.unitemergency.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在行尾追加参数然后按Ctrlx启动。常用的内核参数我列一下systemd.unitrescue.target直接启动到救援模式systemd.unitemergency.target直接启动到紧急模式rd.break在initramfs阶段中断进入dracut shellquiet内核启动时少打印信息出问题排查时要删掉这个参数rhgbRed Hat图形启动画面排查问题时建议删除举个例子。系统开机卡在黑屏但没完全死机你按e进GRUB编辑把quiet rhgb两个参数去掉按Ctrlx重新启动。这时你能看到内核启动时一行行刷屏的输出屏幕卡在哪一行往往就是问题线索所在。我在实际工作中遇到过卡在Starting Login Service...的情况看起来像是systemd的登录服务起不来去掉quiet rhgb后才发现是磁盘I/O错误反复重试导致的。这个线索如果不看启动日志光靠猜很难定位。4.2 查看启动日志journalctl不是只能看当前系统排障时需要看启动日志journalctl是主力工具# 查看本次启动日志 journalctl -b # 查看上一次启动日志 journalctl -b -1 # 实时跟踪启动日志 journalctl -f # 查看启动耗时排行 systemd-analyze blamesystemd-analyze blame是一个很容易被忽略的好用命令。它列出每个服务启动花了多少时间按从长到短排序。排查“开机慢”问题时用这个命令一眼就能看到是哪个服务在拖后腿我之前遇到过一个Docker服务每次启动要等60秒超时的案例就是靠这个命令快速定位的。4.3 GRUB菜单坏了怎么办从安装介质引导rescue模式如果你改坏了GRUB配置或者写错了内核参数导致系统根本进不了GRUB菜单这时候还有一个终极入口用RHEL安装光盘/U盘启动进入rescue模式。在安装介质启动菜单里选择“Troubleshooting”→“Rescue a Red Hat Enterprise Linux system”系统会扫描现有安装然后给你三个选项Continue自动探测并把现有系统挂载到/mnt/sysimageRead-Only mount只读挂载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里。这时候真正的根文件系统还没挂载但你可以在这个阶段做手脚。具体步骤重启系统在GRUB菜单按e编辑找到linux那一行在行尾追加rd.break按Ctrlx启动系统会卡在类似switch_root:/#的提示符执行mount -o remount,rw /sysroot把根文件系统以读写方式重新挂载执行chroot /sysroot切换进真正的根环境执行passwd root重置密码如果之前启用过SELinux执行touch /.autorelabel让下次启动时自动重新打SELinux标签执行exit退出chroot再执行exit或reboot -f重启注意第7步RD.break方法会绕过SELinux的进程标签设置如果直接重启系统可能因为SELinux上下文不正确而拒绝root登录。加了/.autorelabel之后重启过程中SELinux会重新标记整个文件系统虽然耗时稍长但能避免诡异的权限问题。5.2 resuce模式重置密码的替代思路rd.break不是唯一的路子。用前面说的安装介质救援模式也可以流程类似进rescue shell、chroot /mnt/sysimage、passwd root、exit、重启。还有一个思路值得提一下如果你手上正好有另一台能登录这台机器的方式比如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 解决过程重启进入GRUB编辑添加systemd.unitemergency.target跳过所有fstab挂载直接进emergency模式进emergency模式后先mount -o remount,rw /把根文件系统改为可写用vi打开/etc/fstab注释掉新加的那行mount -a测试所有挂载点能否正常挂载确认无误后执行reboot系统恢复正常。整个过程没有用到安装介质靠的就是在GRUB阶段向内核传递systemd.unitemergency.target这个参数。这个案例的教训是改fstab之前一定要用mount -a做dry-run测试或者至少确认挂载点目录已存在。我当时是没先建挂载点目录导致systemd认为该挂载永远失败从而阻塞了依赖它的所有后续单元。7. 把这章内容真正变成自己的几条实操建议控制启动过程这章光看书做题是学不踏实的它是一门“动手技能”。我建议你有条件的话在虚拟机里把这些实验做一遍最基础的一组实验是启动目标切换——把一个运行中的系统从multi-user切到graphical再切回来体会一下isolate和set-default的差异。第二组实验是启动参数传递。在GRUB菜单里删掉quiet rhgb观察启动输出的详细程度差异追加systemd.unitrescue.target和emergency.target分别体验两种模式里的环境差异——文件系统是否只读、网络是否可用、哪些服务在跑。第三组实验是密码重置。在虚拟机里按rd.break的流程完整走一遍包括touch /.autorelabel的步骤然后把重置后的系统重启观察SELinux的relabel过程。做过一遍之后你就知道为什么这个步骤不能省。第四组实验是破坏和修复。故意改坏一个服务的配置比如把nginx的配置改成语法错误或者往fstab里加一个错误的条目然后重启体会启动卡住时排查的完整过程。修复之后再想想如果连这个服务都起不来我还能用什么方式进入系统这组实验做完你对启动过程的理解会有一个质的飞跃。到时候再回头看systemctl list-units --typetarget的输出你看到的就不是一串名字而是一张张可以按需切换的状态网络图。启动过程就像一栋楼的消防通道——平时没人走但真出事的时候能不能快速找到入口、顺利到达想去的地方全靠平时对路线的熟悉程度。RH134这章教的就是这条消防通道的每一道门、每一个转弯、每一个应急开关。把这张地图刻在脑子里比多记几条命令值钱得多。
返回列表