系统启动流程:从按下电源键到用户界面
大家好,我是老张。今天我们来聊聊系统启动流程。说实话,这可能是整个运维生涯里最基础也最关键的知识点。你想想看,服务器起不来,你连门都进不去,还谈什么后续排查?
我个人习惯把启动流程分成四个阶段:BIOS/UEFI、Bootloader、内核加载、init进程启动。每个阶段都有它独特的日志特征和排查技巧。咱们一个一个来看。
第一阶段:BIOS/UEFI 阶段
按下电源键的那一刻,CPU 首先执行的是固化在主板 ROM 里的代码。这就是 BIOS 或 UEFI。说白了,它负责最底层的硬件自检和初始化。
BIOS(Basic Input/Output System) 是老传统了,16位实模式,界面蓝底白字。而 UEFI(Unified Extensible Firmware Interface) 是后来者,32位或64位,支持图形界面,启动更快。
我在项目中遇到过一台老服务器,每次开机都要等 3 分钟才过 BIOS。后来发现是内存自检卡住了。嗯,这里要注意:BIOS 阶段的日志通常不写入操作系统,你得看屏幕输出或者主板上的 Debug 灯。
关键日志位置:
- 屏幕输出:POST 卡(Power-On Self-Test)信息
- 主板蜂鸣器:不同长短音代表不同错误
- IPMI/BMC 日志:远程管理卡可以记录硬件事件
常见的排查点:
- 内存条接触不良?重新插拔试试
- 硬盘没识别?检查 SATA/SAS 线缆
- 启动顺序错了?进 BIOS 调整 Boot Order
我的小技巧: 遇到 BIOS 阶段卡住,先看键盘灯。如果 Num Lock 灯能切换,说明 CPU 和基本电路没问题。如果灯都不亮,那大概率是主板或电源挂了。
第二阶段:Bootloader 阶段
BIOS/UEFI 自检通过后,会按照启动顺序去读取磁盘的第一个扇区(MBR)或者 EFI 系统分区。这里的主角就是 Bootloader。
Linux 下最常见的 Bootloader 是 GRUB2(Grand Unified Bootloader version 2)。它负责加载内核到内存,并传递启动参数。
我曾经遇到过一个经典问题:系统更新后重启,直接黑屏。后来发现是 GRUB 配置文件被改坏了。你想想看,Bootloader 阶段的日志非常有限,基本只能靠屏幕上的错误信息来判断。
GRUB2 的配置文件位置:
/boot/grub2/grub.cfg # 主配置文件(不要手动编辑)
/etc/default/grub # 用户可编辑的配置
grub2-mkconfig -o /boot/grub2/grub.cfg # 重新生成配置
常见的 Bootloader 错误:
- Error: No such partition —— 分区表变了,或者磁盘顺序变了
- Error: File not found —— 内核文件或 initramfs 丢失
- grub rescue> 提示符 —— GRUB 找不到配置文件,进入救援模式
避坑指南: 我曾经手贱直接编辑了 /boot/grub2/grub.cfg,结果重启后系统起不来。记住,永远通过 /etc/default/grub 修改,然后用 grub2-mkconfig 生成。这是血的教训。
第三阶段:内核加载阶段
Bootloader 把内核和 initramfs 加载到内存后,就把控制权交给了内核。内核开始解压自身,初始化硬件驱动,挂载根文件系统。
这个阶段的日志会输出到内核环形缓冲区(kernel ring buffer),你可以用 dmesg 命令查看。我个人习惯在排查启动问题时,第一时间看 dmesg | grep -i error。
内核启动参数:
# 在 GRUB 启动时按 e 编辑,可以添加或修改参数
quiet # 减少输出信息
verbose # 输出详细信息
single # 进入单用户模式
rd.break # 在 initramfs 阶段中断,进入 shell
我印象最深的一次排查:一台新服务器启动到一半就重启了。用 dmesg 一看,发现是 ACPI 报错,内核 panic 了。后来加了 acpi=off 参数才启动成功。嗯,这其实是 BIOS 和内核的兼容性问题。
内核阶段的关键日志:
| 日志来源 | 查看命令 | 说明 |
|---|---|---|
| 内核环形缓冲区 | dmesg | 实时查看内核消息 |
| 系统日志 | journalctl -k | systemd 管理的内核日志 |
| 串口输出 | console=ttyS0 | 通过串口捕获启动日志 |
我的经验: 如果系统完全起不来,可以在 GRUB 启动参数里加上 console=ttyS0,115200,然后用串口线连到另一台电脑上捕获日志。这样就能看到内核 panic 的完整信息了。
第四阶段:init 进程启动
内核挂载根文件系统后,会启动第一个用户空间进程 —— init。在传统 SysVinit 系统中,它是 /sbin/init。在现代系统中,它通常是 /lib/systemd/systemd。
init 进程的 PID 永远是 1。它负责启动所有其他系统服务。说白了,它就是所有进程的祖宗。
SysVinit vs systemd:
| 特性 | SysVinit | systemd |
|---|---|---|
| 启动方式 | 串行启动 | 并行启动 |
| 配置文件 | /etc/inittab | /etc/systemd/system/ |
| 日志管理 | /var/log/messages | journalctl |
| 依赖管理 | 手动编写脚本 | 自动处理依赖 |
我曾经在 CentOS 6 上遇到过一个问题:某个服务启动失败,导致后续所有服务都卡住了。因为 SysVinit 是串行启动的,一个挂了后面全完蛋。换成 systemd 后,并行启动确实快了很多,但排查起来也更复杂了。
systemd 的启动分析工具:
# 查看启动耗时
systemd-analyze
# 查看每个服务的启动时间
systemd-analyze blame
# 查看启动过程中的关键事件
journalctl -b -p err
# 查看特定服务的启动日志
journalctl -u sshd.service
init 阶段常见问题:
- 服务启动超时 —— 检查服务配置和网络依赖
- 文件系统挂载失败 —— 检查 /etc/fstab
- selinux 策略阻止 —— 查看 audit.log
- 磁盘空间不足 —— 根分区满了,服务起不来
避坑指南: 我曾经在 /etc/fstab 里写错了一个挂载点,结果系统启动到一半就进入 emergency mode。记住,修改 fstab 前一定要备份,而且最好用 mount -a 先测试一下。
好了,四个阶段都讲完了。总结一下我的个人经验:
- BIOS/UEFI 阶段 —— 看硬件指示灯和蜂鸣器
- Bootloader 阶段 —— 看屏幕错误信息,进 rescue 模式修复
- 内核加载阶段 —— 用 dmesg 或串口捕获日志
- init 进程启动 —— 用 journalctl 和 systemd-analyze 分析
你想想看,启动流程就像一条流水线。每个环节都有它独特的日志特征。掌握了这些,下次遇到系统起不来的问题,你就知道该从哪里下手了。
公众号:蓝海资料掘金营,微信deep3321