从按下电源到登录界面:CentOS 7 启动原理深度拆解,附 root 密码重置与故障排查实战

从按下电源到登录界面:CentOS 7 启动原理深度拆解,附 root 密码重置与故障排查实战

作者:闲云野鹤在人间
日期:2026-08-19
环境:CentOS 7 / RHEL 7 系列


摘要

你有没有想过,从按下机箱电源键的那一刻起,到屏幕上出现熟悉的登录提示符,这短短几十秒里电脑到底经历了什么?CentOS 7 的启动过程远比想象中复杂:POST 自检、MBR 引导、GRUB2 菜单、内核加载、initramfs 临时根文件系统、systemd 接管……每一步都环环相扣,任何一个环节出问题都可能导致系统起不来。本文从 CentOS 7 的完整启动流程讲起,系统梳理 systemd target 与传统运行级别的对应关系,详细演示两种重置 root 密码的方法(官方推荐的 rd.break 和兼容旧版的 init=/bin/bash),并逐一排查 /etc/fstab 配置错误引发的三类典型启动故障,最后讲解 GRUB2 配置文件的结构与自定义方法。全文所有实验步骤和命令输出均完整保留,拿来就能复现,是一篇真正能帮你"看懂启动、搞定故障"的实战指南。


前言

很多运维新手对 Linux 启动过程的认知停留在"按电源→等一会儿→输密码登录"这个层面。但一旦系统起不来了,面对黑屏上那几行报错,整个人就懵了——到底是 GRUB 坏了?还是 fstab 写错了?还是文件系统炸了?

这篇博客我们就把 CentOS 7 的启动过程从头到尾拆解得明明白白,并且附上最常见的几类启动故障的实战排查方法。看完之后,再遇到系统启动失败,你至少能定位到"卡在第几步了",然后对症下药。


一、CentOS 7 启动过程全流程

现代计算机系统是硬件与软件的复杂组合。从断电状态开始,到拥有登录提示符的运行中系统,需要大量硬件和软件配合工作。

以下从较高层面概述启动 CentOS 7 的物理 X86_64 系统所涉及的任务:

  1. 开机自检(POST)
  2. MBR 引导
  3. GRUB 菜单
  4. 加载内核
  5. 运行 system 进程(systemd)

下面逐步拆解每一步。

步骤 1:开机自检(POST)

计算机接通电源。系统固件(现代 UEFI 或更旧的 BIOS)运行开机自检(POST),并开始初始化硬件。

配置方式:在系统启动早期,通过按特定组合键(例如 F2)进入系统固件设置界面进行配置。

步骤 2:MBR 引导

系统固件搜索启动设备,根据固件配置的顺序搜索启动磁盘上的主启动记录(MBR)。系统固件从磁盘读取 boot loader,然后将系统控制权交给 boot loader——这个 boot loader 就是 GRand Unified Bootloader version 2(GRUB2)

配置方式:使用 grub2-install 命令进行配置,它将安装 GRUB2 作为磁盘上的启动加载器。

步骤 3:GRUB2 菜单

GRUB2 从 /boot/grub2/grub.cfg 文件加载配置并显示一个操作系统菜单,可以从中选择要启动的系统。

配置方式:使用 /etc/grub.d/ 目录、/etc/default/grub 文件和 grub2-mkconfig 命令进行配置,以生成 /boot/grub2/grub.cfg 文件。

步骤 4:加载内核与 initramfs

boot loader 根据选定条目的配置,从磁盘中加载 kernelinitramfs,并将它们放入内存中。

  • initramfs 是一个存档,其中包含启动时所有必要硬件的内核模块、初始化脚本等等。
  • boot loader 将控制权交给 kernel,并同时将启动项的内核参数、initramfs 在内存中的位置传递给 kernel。
  • 内核在 initramfs 中找到所有硬件驱动程序,并初始化这些硬件。

配置方式:使用 /etc/dracut.conf.d/ 目录、dracut 命令和 lsinitrd 命令进行配置,以检查 initramfs 文件。

步骤 5:执行 /sbin/init(PID 1)

initramfs 执行 /sbin/init,作为 PID 1。在 CentOS 7 中,/sbin/init 是一个指向 systemd 的链接。

配置方式:使用内核参数 init=command 配置系统初始化程序。

步骤 6:加载 default.target

随后,systemd 会加载从内核命令行传递的 target,或者加载系统配置的 default.target。该目标通常启动一个基于文本的登录或图形登录屏幕。

配置方式:使用 systemctl 设置默认 target。

步骤 7:sysinit.target 初始化系统

default.target 依赖 sysinit.target,sysinit.target 用于初始化系统,例如读取 /etc/fstab 挂载文件系统、激活 systemd-journald 等。

配置方式:使用 /etc/fstab 配置文件系统开机自动挂载。

步骤 8:激活开机启动单元

default.target 还会激活开机启动的单元(各种服务)。

配置方式:使用 systemctl 设置开机启用服务。

步骤 9:getty.target 打开终端

default.target 还会激活 getty.target,该 target 将打开 tty1 终端用于用户登录。

至此,你就看到了熟悉的登录提示符。


二、系统 target 与运行级别

2.1 什么是 target?

systemd 使用类型为 target 的单元来分组不同单元。例如 multi-user.target 包含 chronyd.servicecrond.servicefirewalld.service 等服务。

target 还可以包含其他 target,形成层级依赖关系:

  • graphical.target 包含 multi-user.target
  • multi-user.target 包含 basic.target
  • basic.target 包含 sysinit.target

2.2 查看 target 依赖关系

使用以下命令查看 target 之间的依赖关系:

[root@localhost ~]# systemctl list-dependencies graphical.target
graphical.target
○ ├─display-manager.service
○ ├─systemd-update-utmp-runlevel.service
○ ├─udisks2.service
● └─multi-user.target
●   ├─auditd.service
●   ├─crond.service
●   ├─dbus.service
●   ├─irqbalance.service
●   ├─kdump.service
○   ├─mdmonitor.service
●   ├─NetworkManager.service
○   ├─restorecond.service
●   ├─rngd.service
●   ├─rsyslog.service
●   ├─sshd.service
●   ├─systemd-ask-password-wall.path
●   ├─systemd-logind.service
○   ├─systemd-update-utmp-runlevel.service
●   ├─systemd-user-sessions.service
●   ├─systemtap.service
●   ├─tuned.service
●   ├─basic.target
●   │ ├─-.mount
●   │ ├─tmp.mount
●   │ ├─paths.target
●   │ ├─slices.target
●   │ │ ├─-.slice
●   │ │ └─system.slice
●   │ ├─sockets.target
●   │ │ ├─dbus.socket
●   │ │ ├─dm-event.socket
●   │ │ ├─pcscd.socket
●   │ │ ├─systemd-coredump.socket
●   │ │ ├─systemd-initctl.socket
●   │ │ ├─systemd-journald-dev-log.socket
●   │ │ ├─systemd-journald.socket
●   │ │ ├─systemd-udevd-control.socket
●   │ │ └─systemd-udevd-kernel.socket
●   │ ├─sysinit.target
●   │ │ ├─dev-hugepages.mount
●   │ │ ├─dev-mqueue.mount
●   │ │ ├─dracut-shutdown.service
●   │ │ ├─hwclock-save.service
●   │ │ ├─kmod-static-nodes.service
○   │ │ ├─ldconfig.service
●   │ │ ├─lvm2-lvmpolld.socket
●   │ │ ├─lvm2-monitor.service
●   │ │ ├─proc-sys-fs-binfmt_misc.automount
●   │ │ ├─sys-fs-fuse-connections.mount
●   │ │ ├─sys-kernel-config.mount
●   │ │ ├─sys-kernel-debug.mount
●   │ │ ├─sys-kernel-tracing.mount
●   │ │ ├─systemd-ask-password-console.path
○   │ │ ├─systemd-binfmt.service
○   │ │ ├─systemd-hwdb-update.service
○   │ │ ├─systemd-journal-catalog-update.service
●   │ │ ├─systemd-journal-flush.service
●   │ │ ├─systemd-journald.service
○   │ │ ├─systemd-machine-id-commit.service
●   │ │ ├─systemd-modules-load.service
●   │ │ ├─systemd-network-generator.service
●   │ │ ├─systemd-random-seed.service
●   │ │ ├─systemd-sysctl.service
○   │ │ ├─systemd-sysusers.service
●   │ │ ├─systemd-tmpfiles-setup-dev-early.service
●   │ │ ├─systemd-tmpfiles-setup-dev.service
●   │ │ ├─systemd-tmpfiles-setup.service
●   │ │ ├─systemd-udev-trigger.service
●   │ │ ├─systemd-udevd.service
○   │ │ ├─systemd-update-done.service
●   │ │ ├─systemd-update-utmp.service
●   │ │ ├─cryptsetup.target
●   │ │ ├─integritysetup.target
●   │ │ ├─local-fs.target
●   │ │ │ ├─-.mount
●   │ │ │ ├─boot-efi.mount
●   │ │ │ ├─boot.mount
●   │ │ │ ├─systemd-fsck-root.service
●   │ │ │ ├─systemd-remount-fs.service
●   │ │ │ └─tmp.mount
●   │ │ ├─swap.target
●   │ │ │ └─dev-mapper-openeuler\x2dswap.swap
●   │ │ └─veritysetup.target
●   │ └─timers.target
●   │   ├─dnf-makecache.timer
●   │   └─systemd-tmpfiles-clean.timer
●   ├─getty.target
●   │ └─getty@tty1.service
●   └─remote-fs.target
[root@localhost ~]#

查看反向依赖(哪些 target 依赖了某个服务):

[root@localhost ~]# systemctl list-dependencies sshd.service --reverse
sshd.service
● └─multi-user.target
○   └─graphical.target
[root@localhost ~]#

可以看到 sshd.servicemulti-user.target 依赖,而 multi-user.target 又被 graphical.target 依赖。

2.3 运行级别与 target 对照表

CentOS 6 之前使用**运行级别(runlevel)**控制系统开机激活哪些服务。CentOS 7 之后使用 target 控制。

runleveltarget作用
0关机。init 0poweroffsystemctl poweroff
1emergency.target / rescue.target单用户模式、救援模式和紧急模式,用于修复系统
2多用户文本界面,不具备 NFS 功能
3multi-user.target多用户文本界面
4未使用
5graphical.target多用户图形界面
6重启。init 6rebootsystemctl reboot

2.4 /etc/inittab 文件(历史遗留)

/etc/inittab 文件是 RHEL 6 之前版本初始化系统使用的配置文件。在 CentOS 7 中,这个文件基本不再使用,但仍保留了一些注释说明:

# 部分内容如下
# Default runlevel. The runlevels used by RHS are:
#   0 - halt (Do NOT set initdefault to this)
#   1 - Single user mode
#   2 - Multiuser, without NFS (The same as 3, if you do not have networking)
#   3 - Full multiuser mode
#   4 - unused
#   5 - X11
#   6 - reboot (Do NOT set initdefault to this)
#
# 设置运行级别为 5 ,也就是图形化方式启动。
id:5:initdefault:

三、设置系统运行目标

3.1 设置系统当前运行 target

使用 systemctl isolate 命令切换当前运行的 target:

# 设置系统当前运行 target 为 multi-user.target
[root@localhost ~]# systemctl isolate multi-user.target

# 设置系统当前运行 target 为 graphical.target
[root@localhost ~]# systemctl isolate graphical.target

3.2 设置系统开机默认运行 target

# 查看系统开机默认运行 target
[root@localhost ~]# systemctl get-default
multi-user.target

# 设置系统开机默认运行 target
[root@localhost ~]# systemctl set-default multi-user.target

# 重启验证
[root@localhost ~]# reboot

3.3 在系统启动时选择其它目标

要在启动时选择其他目标,将 systemd.unit=target.target 参数附加到内核命令行。该配置是临时生效的,经常用于系统启动过程中的故障排除。

操作步骤:

  1. 启动或重新启动系统。
  2. 按任意键(Enter 除外,它用于执行正常启动)中断启动加载器菜单倒计时。
  3. 将光标移至要启动的内核条目。
  4. e 编辑当前条目。
  5. 将光标移至以 linux 开头的行(此为内核命令行)。
  6. 附加 systemd.unit=target.target。例如,systemd.unit=emergency.target
  7. Ctrl+x 使用这些更改进行启动。

四、重置 ROOT 密码

如果管理员仍处于登录状态,不管是作为拥有完全 sudo 访问权限的非特权用户,还是作为 root 用户,这个任务都很简单,直接执行 passwd 命令设置即可。

但如果管理员未登录,任务就变得略微复杂了。

在 CentOS 6 及更早版本中,管理员可以将系统启动到 runlevel 1 以获得 root 提示符。在 CentOS 7 之后,与 runlevel 1 最接近的模式是紧急目标(emergency.target)救援目标(rescue.target),但这两个目标都需要 root 密码才能登录——这就陷入了死循环。

以下介绍两种重置 root 密码的方法。

方法 1:rd.break(官方推荐,优先用)

中断点:initramfs 阶段,还没有切换真实根,提示符为 switch_root:/#

操作步骤:

  1. 重新启动系统。
  2. 按任意键(Enter 除外)中断启动加载器倒计时。
  3. 将光标移至要启动的内核条目。
  4. e 编辑选定的条目。
  5. 将光标移到内核命令行(以 linux 开头的行)。
  6. 附加 rd.break。利用该选项,在系统从 initramfs 向实际系统移交控制权前,系统将会中断。

    kernel 行可能有多个 console 参数,以最后一个为准,有些时候需要设置 console=tty0

  7. Ctrl+x 使用这些更改进行启动。
  8. 此时,系统会显示 root shell,且磁盘上的实际根文件系统以只读方式挂载在 /sysroot
  9. 以读/写形式重新挂载 /sysroot
  10. 切换 root 位置,把 /sysroot 作为文件系统树的根(chroot)。
  11. 设置新 root 密码。
  12. 如果系统开启了 SELinux 功能,则需要确保所有未标记的文件(包括此时的 /etc/shadow)在启动过程中都会重新获得标记。
  13. 键入 exit 两次。第一个命令将退出 chroot 存放位置,第二个命令将退出 initramfs 调试 shell。此时系统将继续进行启动,执行完整的 SELinux 重新标记,然后再次重新启动。
  14. 登录验证。

具体命令:

switch_root:/# mount -o remount,rw /sysroot
switch_root:/# chroot /sysroot
sh-4.2# passwd root
sh-4.2# touch /.autorelabel

然后输入两次 exit,系统会继续启动并自动执行 SELinux 重新标记。

方法 2:init=/bin/bash

作用:内核启动完,不启动 systemd(PID1),直接把 /bin/bash 作为 PID=1,直接拿到系统 shell。此时根文件系统默认只读挂载

操作步骤:

  1. 重新启动系统。
  2. 按任意键(Enter 除外)中断启动加载器倒计时。
  3. 将光标移至要启动的内核条目。
  4. e 编辑选定的条目。
  5. 将光标移到内核命令行(以 linux 开头的行)。
  6. 附加 init=/bin/bash。利用该选项,在系统从 initramfs 向实际系统移交控制权前,系统将会中断,开启一个 root shell。

    kernel 行可能有多个 console 参数,以最后一个为准,有些时候需要设置 console=tty0

  7. Ctrl+x 使用这些更改进行启动。
  8. 此时,系统会显示 root shell,且磁盘上的实际根文件系统以只读方式挂载在 /
  9. 以读/写形式重新挂载 /
  10. 设置新 root 密码。
  11. 如果系统开启了 SELinux 功能,则需要确保所有未标记的文件(包括此时的 /etc/shadow)在启动过程中都会重新获得标记。
  12. 执行 exec /sbin/init,拉起 systemd 正常走完启动流程。

具体命令:

bash-4.2# mount -o remount,rw /
sh-4.2# passwd
sh-4.2# touch /.autorelabel
sh-4.2# exec /sbin/init

两种方法对比

对比项rd.breakinit=/bin/bash
中断阶段initramfs,切换真实根之前已经切换到真实根,替代 systemd(PID1)
根文件系统位置真实根在 /sysroot,需要 chroot直接就是真实系统 /
SELinux依然生效,必须写 /.autorelabel依然生效,也要 /.autorelabel
磁盘支持LVM、RAID、iSCSI 都正常识别,initramfs 驱动完整同样加载 initramfs,磁盘驱动正常
退出方式两次 exit,正常继续启动不能直接断电/重启,必须执行 exec /sbin/init
风险点几乎无风险,官方标准方式忘记 exec /sbin/init 直接重启,极易损坏文件系统
官方态度RHEL/CentOS 官方文档标准方案兼容旧方式,不推荐生产使用

总结:生产环境优先用 rd.break,安全可靠。init=/bin/bash 作为备选方案了解即可。


五、/etc/fstab 引起的系统启动问题

/etc/fstab 是系统开机自动挂载文件系统的配置文件。如果这个文件写错了,很可能导致系统启动失败,进入 emergency 模式。下面我们通过三个典型故障来演示如何排查和修复。

环境准备

首先准备一个测试用的磁盘分区:

# 设置磁盘分区管理方案
[root@centos79 ~]# parted /dev/sdb mklabel msdos

# 创建分区
[root@centos79 ~]# parted /dev/sdb unit MiB mkpart primary 1 10241

# 格式化为 xfs 文件系统
[root@centos79 ~]# mkfs.xfs /dev/sdb1

# 创建挂载点
[root@centos79 ~]# mkdir /data01

# 设置持久化挂载
[root@centos79 ~]# echo '/dev/sdb1 /data01 xfs defaults 0 0' >> /etc/fstab

# 挂载并验证
[root@centos79 ~]# mount -a
[root@centos79 ~]# df -h /data01
文件系统        容量   已用   可用  已用% 挂载点
/dev/sdb1       10G   33M    10G    1%   /data01

故障 1:挂载点不存在

环境准备:

[root@centos79 ~]# umount /data01
[root@centos79 ~]# rmdir /data01

重启系统验证:

系统可以正常进入系统,挂载点会被自动创建:

[root@centos79 ~]# df -h /data01
文件系统        容量   已用   可用  已用% 挂载点
/dev/sdb1       10G   33M    10G    1%   /data01

结论:挂载点不存在不会导致系统启动失败,systemd 会自动创建挂载点。

故障 2:设备名称写错或者找不到设备

环境准备:

[root@centos79 ~]# vim /etc/fstab
# 将原先的 sdb1 修改为 sdb2
/dev/sdb2 /data01 xfs defaults 0 0

重启系统验证:

  1. 启动过程中找不到该设备。
  2. 1 分 30 秒超时后,进入 emergency 模式,输入密码,进行修复。

修复方法:

  1. 修改为正确的值或者注释该条目,确保系统正常启动。
  2. 然后输入 reboot,重新启动系统。如果系统没有继续启动,则可以强制关机重启。

故障 3:破坏文件系统

环境准备:

[root@centos79 ~]# dd if=/dev/zero of=/dev/sdb1 bs=1M count=1

这条命令用零覆盖了 /dev/sdb1 的前 1MB,彻底破坏了文件系统超级块。

重启系统验证:

  1. 系统启动过程中尝试修复文件系统,修复失败后提示进入 emergency 模式修复。
  2. 进入 emergency 模式修复。

修复命令:

# 执行以下命令修复
[root@centos79 ~]# xfs_repair /dev/sdb1

修复完成后,输入 exit 继续启动系统,系统可以正常启动。

注意:如果文件系统损坏严重,xfs_repair 可能无法修复,需要重新格式化并恢复数据。所以重要数据一定要有备份!


六、GRUB2 配置

6.1 GRUB2 主要配置文件

GRUB2 的主要配置文件和目录如下:

路径说明
/boot/grub2/GRUB2 的主要配置文件所在目录,例如 grub.cfggrubenvuser.cfg
/etc/grub2.cfg指向 /boot/grub2/grub.cfg 的软链接
/etc/grub2-efi.cfg使用 EFI 启动方式的 GRUB2 配置文件
/etc/grub.d/存放多个数字开头的脚本,按照从小到大的顺序执行。例如 00_header 会调用 /etc/default/grub 配置文件来实现最基本的开机界面配置
/etc/default/grub定义 grub 启动部分变量信息,例如 grub 启动菜单选择条目的超时时间、内核参数等
/boot/grub2/grubenv设定默认启动条目

重要提醒:不要直接修改 /etc/grub2.cfg 文件,该文件由系统自动生成。如果需要自定义,通过修改 /etc/grub.d/ 中的脚本和 /etc/default/grub 文件,然后通过 grub2-mkconfig 命令生成。

6.2 修改 GRUB2 菜单超时时间

编辑 /etc/default/grub 文件,修改 GRUB_TIMEOUT 参数:

[root@centos79 ~]# vim /etc/default/grub
# 修改 GRUB_TIMEOUT 为 10
GRUB_TIMEOUT=10

生成配置文件使其生效:

[root@centos79 ~]# grub2-mkconfig -o /etc/grub2.cfg
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-3.10.0-1160.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-1160.el7.x86_64.img
Found linux image: /boot/vmlinuz-0-rescue-c6e36d35c9a846d7b64d9fdf929b09f6
Found initrd image: /boot/initramfs-0-rescue-c6e36d35c9a846d7b64d9fdf929b09f6.img
done

重启验证:

[root@centos79 ~]# reboot

重启后 GRUB2 菜单的倒计时就变成了 10 秒。


总结

回顾一下这篇博客的核心知识点:

  1. CentOS 7 启动九步走:POST 自检 → MBR/GRUB2 引导 → GRUB2 菜单 → 加载 kernel + initramfs → 执行 /sbin/init(systemd,PID 1)→ 加载 default.target → sysinit.target 初始化(挂载 fstab 等)→ 激活开机服务 → getty.target 打开登录终端。

  2. systemd target 替代运行级别:CentOS 7 用 target 替代了传统的 runlevel。multi-user.target 对应级别 3(文本界面),graphical.target 对应级别 5(图形界面)。用 systemctl isolate 切换当前 target,systemctl set-default 设置开机默认 target。

  3. 重置 root 密码:官方推荐 rd.break 方法(在 initramfs 阶段中断,chroot 到 /sysroot 改密码,touch /.autorelabel 处理 SELinux,两次 exit 继续启动)。备选方案 init=/bin/bash 直接拿 shell,但必须 exec /sbin/init 正常退出,否则容易损坏文件系统。

  4. fstab 故障排查:挂载点不存在会自动创建(不影响启动);设备名写错会超时 1 分 30 秒后进 emergency 模式;文件系统损坏需要用 xfs_repair 修复。遇到启动失败进 emergency 模式,第一反应就是去检查 /etc/fstab

  5. GRUB2 配置:不要直接改 grub.cfg,改 /etc/default/grub/etc/grub.d/ 下的脚本,然后用 grub2-mkconfig -o /etc/grub2.cfg 重新生成。

最后说一句:Linux 启动看起来复杂,但只要你理解了每一步在干什么,遇到启动故障时就能快速定位到"卡在哪一步",然后针对性修复。别一看到黑屏就慌,先想想它走到第几步了。


本文基于 CentOS 7 系统启动原理课程材料整理,所有实验步骤均可直接复现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值