在操作系统安装部署与日常维护中,有两个看似独立却深刻反映系统底层设计的问题经常被提及:从 ISO 启动时 GRUB 菜单里的"救援模式"到底做了什么,为什么能拯救一台"半残"的服务器?以及,为什么同样是 Linux 内核,x86 服务器的启动日志通常哗啦啦刷在显示器上(tty0),而 ARM 板子却总要从串口(ttyS0)里读输出?本文将从底层原理出发,把这两个问题讲透,并揭示它们在架构哲学上的差异。
一、ISO 启动时 GRUB 入口的"救援模式"解密
1.1 两种"救援"需要先分清
说起 GRUB 和救援,新手容易混淆两个概念:
-
GRUB Rescue Shell (
grub rescue>)这是 GRUB 自己的紧急模式。当 GRUB 找不到
grub.cfg配置文件、无法识别分区,或者核心模块丢失时,就会掉进这个极简的命令行。它能做的事情非常有限,只能加载必要模块、手动指定内核与 initrd 路径,目标是"救活 GRUB 本身"。 -
系统救援模式 (Rescue Mode)
本文重点。这是安装 ISO 启动菜单中的一个启动项,常见标题如 "Rescue a CentOS system" 、"Rescue mode" 或 "Troubleshooting"。它其实是一个完整的临时 Linux 环境,专门用来修复已安装但无法正常启动的操作系统。
1.2 系统救援模式能做什么?
当你把安装盘作为急救盘使用时,救援模式可以:
- 挂载目标系统的根文件系统并进行
chroot - 修复损坏的 GRUB / systemd-boot 引导
- 重置遗忘的 root 密码
- 修复错误的
/etc/fstab、网卡配置、SELinux 标签 - 重建 initramfs、重装内核
- 在无需重装系统的情况下从致命错误中恢复
本质就是:用一套外来的健康"最小系统"去操作硬盘上那个"生病"的真实系统。
1.3 底层原理:内核 + initramfs + 内核参数的魔法
从技术栈来看,救援模式的启动路径与正常系统相同,只是参数和环境完全不同。
-
引导加载器阶段
ISO 中的 GRUB 会读取特定的菜单条目,向内核传递特殊参数。典型的 x86 条目类似:
linux /isolinux/vmlinuz root=live:CDLABEL=... rd.live.image rescue initrd /isolinux/initrd.img关键字
rescue(某些发行版是single或systemd.unit=rescue.target)就是进入救援模式的钥匙。 -
内核与 initramfs 启动
内核照常初始化,但不会去找硬盘上的根文件系统。它先挂载 initramfs 中的临时根文件系统(一个包含 busybox 和基础工具的内存镜像)。如果是 Live 介质,还会将 squashfs 镜像挂载为
/run/initramfs/live等。 -
救援环境的初始化(以 RHEL/CentOS 为例)
- systemd 检测到
systemd.unit=rescue.target或内核命令行中的rescue,启动rescue.target。 - 该 target 会跳过复杂的网络、图形界面等服务,只拉取基本 shell 和 udev。
- 传统的 SysV init 系统则会识别
single参数,进入单用户模式,直接给出 root shell。 - Anaconda 安装器的救援模式甚至会有交互式脚本:扫描硬盘上的 Linux 安装,询问是否将它们挂载到
/mnt/sysimage,然后自动执行chroot /mnt/sysimage。
- systemd 检测到
-
真正干活的阶段 ------ chroot
当你在救援 shell 中执行
chroot /mnt/sysimage后,进程的根目录会切换到硬盘上的系统。此时运行grub2-install、passwd等工具,修改的全是真实系统的文件。
核心原理一句话总结: 利用 Linux 的"内核 + initramfs 独立启动"能力,完全避开目标磁盘的 init 系统和配置,获得一个干净的控制权,再通过 chroot 返回去修理它。
1.4 systemd 时代的救援目标
现代发行版使用 systemd,救援模式对应的是 rescue.target。它与 emergency.target 的区别在于:
rescue.target:会启动基本的文件系统挂载、日志服务等,等待管理员登录,是"单用户模式的增强版"。emergency.target:启动的组件更少,甚至连根文件系统都以只读方式挂载,只在rescue都无法进入时使用。
内核参数 rd.break 则更为底层,它会在 initramfs 阶段、尚未挂载真实根文件系统之前强制停下,丢给你一个 shell。这是真正的"救命稻草"。
二、为什么 ARM 内核输出是 ttyS0,而 x86 是 tty0?
这个现象背后是历史习惯、硬件设计哲学和内核控制台框架共同作用的结果。
2.1 Linux 控制台设备概念速览
- ttyS0 / ttyAMA0 / ttySAC0:串行控制台,底层对应 UART 硬件。数据通过 TX/RX 引脚发送,你在另一端用 USB 转串口线或调试器接收。
- tty0 :不是真实硬件设备,而是"当前激活的虚拟控制台 "的别名。它指向你正在看的那个文本/图形终端(比如
tty1、tty2)。写东西给tty0,总能在屏幕上看到。 - tty1, tty2, ...:具体的虚拟控制台(VT),通常对应 Ctrl+Alt+F1 ~ F6。
2.2 x86 的默认选择:tty0 虚拟控制台
x86 PC 从 IBM PC 时代起就标配"显卡 + 显示器"作为标准人机交互界面。BIOS/UEFI 固件提供 VGA 文本模式或图形输出协议(GOP),内核初始化时会:
- 注册 VGA 文本控制台(
vgacon)或基于 framebuffer 的fbcon。 - 创建
/dev/tty1、/dev/tty2等虚拟终端。 - 将第一个虚拟终端作为默认内核控制台。
因此,即使你没在启动参数里写 console=tty0,内核在 x86 上也会自动将显卡驱动注册的控制台设为默认输出 。你看到的开机日志就是通过 printk 输出到这里的。
命令行中常见的 console=tty0:其实是显式指定了"将输出发送到虚拟终端",在很多发行版的 GRUB 配置里都能找到,它的作用是确保日志出现在屏幕上,即使同时启用了串口控制台。
2.3 ARM 的默认选择:ttyS0 串行控制台
反观 ARM 生态:
-
历史惯性:绝大多数 ARM 开发板、嵌入式设备没有标准 VGA/HDMI 显示子系统,或者即使有 GPU,也不一定提供 BIOS/UEFI 那样的早期文本输出能力。
-
调试核心是 UART:从单片机时代起,串口就是最廉价、最可靠的调试接口。ARM SoC 内部至少有一组 UART,引出三根线(TX/RX/GND),不需要任何初始化就能在很早的内核阶段输出字符。
-
引导加载器(U-Boot)的传递 :U-Boot 通常把设备树(Device Tree)中的
chosen节点配置好,例如:/ { chosen { stdout-path = "serial0:115200n8"; }; };内核解析设备树后,会将对应的串口驱动(如
pl011、8250)注册为控制台,名称通常是ttyS0或ttyAMA0。 -
内核编译时的默认命令行 :许多 ARM 内核在
CONFIG_CMDLINE中直接写死了console=ttyS0,115200,以防根本没有引导加载器传参的场景。
因此,哪怕 ARM 板子接了显示器,开发者通常还是首选串口来观察内核 Panic 信息 ------ 因为它从 CPU 上电后几毫秒就开始工作了,不会漏掉任何早期日志。
2.4 内核控制台选择机制揭秘
Linux 内核的 printk 输出不是只去一个地方,它可以同时向多个控制台设备输出,控制台的选择优先级如下:
-
命令行参数
console=显式指定 (最重要)可以多次使用,例如:
console=ttyS0,115200 console=tty0这会让内核日志同时出现在串口和屏幕上。最后一个
console=指定的设备会成为/dev/console的默认设备 ,这也是为什么有些系统把console=tty0放在最后。 -
没有
console=参数时的平台默认行为- x86:自动寻找第一个注册的虚拟终端(VT)作为默认控制台。
- ARM:如果没有传递命令行,内核会检查设备树中的
stdout-path;若仍无效,则会使用编译时的默认配置(通常是某个串口)。
-
驱动注册时机
内核启动初期,只有 earlycon(早期控制台)用于最早的日志输出。随后 UART 驱动或 VT 驱动加载,对应的真实控制台设备注册,接管日志输出。
2.5 设计哲学与部署场景
- x86 / 服务器:管理员站在机架前,接个显示器,插上键盘,直接操作。tty0(屏幕)是人机交互的自然选择。
- ARM / 嵌入式:设备常常是"无头"的,部署在无人值守的环境。串口连接廉价、稳定、可远程借助"串口服务器"管理,并且能抓到最完整的引导日志,是调试和部署的生命线。
即使现在的 ARM64 服务器(如鲲鹏、飞腾、Ampere)已经支持 UEFI 和显卡输出,但在数据中心批量管理和 PXE 自动化安装场景下,IPMI 串口重定向(SOL) 仍然通过 ttyS0 提供文本控制台,这是服务器带外管理的核心手段。
结语
ISO 救援模式的优雅在于它完全运用了 Linux 的模块化启动特性,把存储在内核和 initramfs 里的"最小手术室"当作修理工具;而 ARM 与 x86 在控制台选择上的差异,则折射出通用服务器与嵌入式设备在硬件设计、调试习惯上的根本区别。理解这两者,无论是现场紧急抢救系统,还是跨架构部署核心应用,都能让你对 Linux 的掌控力再上一个台阶。