昇腾服务器根分区只读故障:ext4 日志中止 → 远程 fsck + IPMI 全程修复记录

九月 08, 2026 [Linux 与系统] #ipmi #bmc #kunpeng #ascend #310p #systemd #serial #opencode #调试

一、背景与事故环境

项值
服务器鲲鹏 920 aarch64 / 128 核 / 250GB 内存(TaiShan 200 Model 2280)
加速卡2× Atlas 300I Duo = 4× 310P3,每芯 44GB LPDDR4X
系统盘/dev/sda 500GB(单盘无 RAID),/dev/sda2 为 ext4 根分区
数据盘/dev/sdb2 8.7TB,挂载于 /data(模型权重等大数据)
BMCiBMC 3.03.00.69(Web 192.168.6.100,无独立 SOL 客户端功能)
业务vLLM 推理服务(Qwen3.8-27B w8a8)、虚拟机 u24、ollama、opencode-web

一句话结论:根分区只读是 /dev/sda 块层真实 I/O 失败(一次 WRITE + 一次 DISCARD,扇区约 250GB 偏移)→ ext4 journal abort → 内核自我保护重挂 RO。恢复路径:initramfs 停在 BusyBox 等待人工 fsck → ipmitool SOL 直连 → fsck.ext4 -fy /dev/sda2 → 重启,一次成功。


二、事故时间线

时间(CST)事件
9/7 00:25:27/dev/sda 块层 I/O 错误(WRITE + DISCARD)
9/7 00:25:28ext4 检测 journal abort,内核自动重挂根分区分只读
9/7 ~ 9/8系统"带病运行"约 39 小时(journald 持续报 Read-only,服务仍在内存里跑)
9/8 18:2x计划在 :8001 做单卡/双卡 TP 压测 → 发现 docker exec 报 read-only → 定位根分区 RO
9/8 19:0xsystemctl reboot 触发(系统关机卡在 libvirt inhibitor,约 20 分钟后真正重启)
9/8 20:02主机重启,EFI → 内核接管后无网络(VGA 黑屏)
9/8 20:40经 BMC 强制断电再开机,仍无网络(其实是停在 initramfs 等 fsck)
9/8 20:5x~21:4xIPMI 系列排查(视频/CLP/SOL 全试),最终靠串口采集包拿到启动日志
9/8 22:1xipmitool SOL 直连 → 发现 BusyBox (initramfs) → fsck.ext4 -fy 修复
9/8 22:23重启成功,端口 22 恢复,根分区 rw、fs clean

三、事故发现:一个"docker exec 报 read-only"的线索

即将开始压测时,先做一次服务状态盘点,命令本身暴露了异常:

# 对容器执行运行时操作,报错:
# OCI runtime exec failed: open /tmp/runc-process1480382453: read-only file system
docker rm -f <服务容器>    # cannot remove container: read-only file system

随后系统级检查直指根因:

mount | grep " / "
# /dev/sda2 on / type ext4 (ro,relatime)   ← 根分区只读!
df -hT /                                # 显示 /dev/sda2 有 328G 可用——df 不看挂载选项,容易误判

教训 1:df 显示"可用空间正常"不代表可写;判断可写性要看 mount/findmnt 的 ro/rw 选项。


四、根因排查:dmesg 一锤定音

4.1 三个关键证据

# ① 块层错误(真凶)
dmesg -T | grep -iE "blk_update|i/o error"
# [9/7 00:25:27] blk_update_request: I/O error, dev sda, sector 466055824 op 0x3:(DISCARD)
# [9/7 00:25:27] blk_update_request: I/O error, dev sda, sector 491035880 op 0x1:(WRITE)
# [9/7 00:25:27] blk_update_request: I/O error, dev sda, sector 491035880 op 0x1:(WRITE)

# ② 日志中止 → 内核自我保护
dmesg -T | grep -iE "aborted|Remounting"
# [9/7 00:25:28] EXT4-fs error (device sda2): ext4_journal_check_start:83: comm systemd-journal: Detected aborted journal
# [9/7 00:25:28] EXT4-fs (sda2): Remounting filesystem read-only   (连续两行)

# ③ 文件系统元数据损伤
tune2fs -l /dev/sda2 | grep -E "Filesystem state|Errors behavior"
# Filesystem state:         clean with errors   ← 错误标记挡住 remount,rw
# Errors behavior:          Continue
blockdev --getro /dev/sda2; cat /sys/block/sda/ro   # 0 / 0 —— 设备层没写保护,纯文件系统层问题

e2fsck -fn /dev/sda2   (只读预检,安全)
# Inode bitmap differences ... Block bitmap differences: Group 1977 block bitmap does not match checksum.
# /dev/sda2: WARNING: Filesystem still has errors

结论链条:块层 WRITE 失败 → JBD2 日志中止 → 内核重挂 RO → ext4 记录"errors"状态 → mount -o remount,rw 被内核拒绝(报 is write-protected)→ 必须 fsck 清错误。同时确认:磁盘没有 RAID 保护(/dev/sda 单盘直连),任何坏区都是致命的。

4.2 为什么不能在线修复


五、IPMI 排查:视频控制台"没画面"的真相 + 绕过终局

5.1 为什么 IPMI KVM 看不到启动画面

BMC(iBMC 3.03)视频控制台 / KVM 只镜像显卡/VGA输出:

EFI stub: Booting Linux Kernel...
EFI stub: Using DTB from configuration table
EFI stub: Exiting boot services...
(之后黑屏)

这行 EFI stub 是 UEFI/EfiStub 用图形控制台打的最后输出;内核接管后默认走串口(ttyS0),VGA 就再也没内容了——不是 IPMI 没用,是"音频源"开着串口,看错了窗口。这是 ARM 服务器(鲲鹏)的典型配置。

5.2 iBMC 探索一轮:SOL 客户端全缺席

尝试结论
Web 远程控制台 kvm_h5只有视频+工具栏,图标全是 icon-font,DOM 里没有"串口"切换项;我的浏览器页面 Frame:0/Send:0/Recv:0(第二个视频会话拿不到流)
Web 端口服务页未提供 SOL 端口信息(该机型固件无此功能)
iBMC SSH CLPsol → COMMAND NOT SUPPORTED;help 只列 ipmcget/ipmcset/…;无串口命令
ipmcset -d serialdir有! 选项表看清了串口方向矩阵:0 PANEL↔SYS(默认,物理面板)、1 PANEL↔BMC、2 SOL COM↔SYS COM、254 关闭
ipmcget -d systemcom下载系统串口采集包(最近 2MB 环,存 BMC 本地 /tmp/systemcom.tar)——这是本事故的破局点

5.3 破局:串口方向切到 SOL + 采集包提取

  1. ipmcset -d serialdir -v 2(SOL COM↔SYS COM)→ 此后机器的串口输出会灌进 BMC 的采集环;
  2. ipmcget -d systemcom → BMC 打包 /tmp/systemcom.tar(2MB);
  3. SFTP 取文件(iBMC 的 SSH ControlMaster 复用,无需再输密码):
tmux new-session -d -s cm 'cd /tmp && sftp Administrator@192.168.6.100'
# sftp> cd /tmp; get systemcom.tar     → 本地拿到 2MB
tar -xf systemcom.tar && strings systemcom.dat | tail -60
  1. 启动日志最后一屏直接掀翻所有猜测:
Begin: Will now check root file system ... fsck.ext4 -a -C0 /dev/sda2
/dev/sda2 contains a file system with errors, check forced.
/dev/sda2: |                0.1%
/dev/sda2: Inodes that were part of a corrupted orphan linked list found.
/dev/sda2: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.  (i.e., without -a or -p options)
fsck exited with status code 4
Failure: File system check of the root filesystem failed
The root filesystem on /dev/sda2 requires a manual fsck
BusyBox v1.30.1 (Ubuntu 1:1.30.1-7ubuntu3.1) built-in shell (ash)
Enter 'help' for a list of built-in commands
(initramfs)

机器根本没死:initramfs 里 fsck.ext4 -a(自动模式)遇到"UNEXPECTED INCONSISTENCY"不会擅自修复 → 状态码 4 → drop 到 BusyBox 交互 shell 等人工 fsck。注意:此时内核已在跑,所以 BMC 的"Power state On"、EFI/VGA 黑屏、端口 22 不通,全部自洽了。

教训 2:fsck.ext4 -a 不等于 -y。生产上 initramfs 卡在 (initramfs) 提示符时,先看控制台(串口/SOL/采集包),机器往往只是要你带 -y 再跑一次。

5.4 最后一公里:ipmitool SOL 直连

Web 和 CLP 都没有 SOL 通道,但 IPMI LAN SOL 协议还在——用 ipmitool 走 lanplus 即可,密码也是 BMC 的 Administrator 密码(输密码时无回显,不会暴露):

# 本地机安装 ipmitool(1.8.19)后,tmux 里起会话让用户在屏幕上输密码
ipmitool -I lanplus -H 192.168.6.100 -U Administrator sol activate

连上后 (initramfs) 就在眼前——这回是真正能输入输出串口控制台。执行:

fsck.ext4 -fy /dev/sda2
# Fix? yes  × 若干轮
# /dev/sda2: 1188994/30457856 files, 29874374/121820928 blocks  (10-20 秒完成,无坏块挂死!)
sync && reboot -f

20 秒修完——之前"fsck 卡死几小时"的假设是错的,纯粹是停在提示符等人。盘虽然坏了一次写,元数据修复后整体可用。


六、可复用速查

# ① 确认根分区 RO
mount | grep " / "

# ② 找真凶
dmesg | grep -iE "blk_update_request.*I/O error|aborted journal|Remounting"

# ③ 评估修到哪一步
tune2fs -l /dev/sda2 | grep -E "Filesystem state|Errors behavior"   # clean with errors = 需 fsck
e2fsck -fn /dev/sda2                    # 只读预检(安全)
blockdev --getro /dev/sda2; cat /sys/block/sda/ro

# ④ 路由串口到 SOL(iBMC)
ipmcset -d serialdir -v 2   # SOL COM↔SYS COM(0=PANEL↔SYS 物理面板,用完切回)

# ⑤ 拉串口采集包(BMC 已录最近 2MB 串口输出)
ipmcget -d systemcom        # 生成 /tmp/systemcom.tar(BMC 侧)
sftp Administrator@<bmc-ip>; cd /tmp; get systemcom.tar

# ⑥ 直连 SOL 键盘交互
ipmitool -I lanplus -H <bmc-ip> -U Administrator sol activate
# → (initramfs) 里: fsck.ext4 -fy /dev/sda2 && sync && reboot -f

七、延伸:这起事故引出的两个"为什么"(GRUB 与 initramfs)

7.1 为什么启动要过"两个 EFI 程序"(shim → grub)?

背景:UEFI Secure Boot 开启时,固件只执行"白名单签名"的 EFI 程序(主板出厂烙有板厂 CA + Microsoft UEFI CA)。Linux 发行版的 grubaa64.efi、vmlinuz 用发行版自己的密钥签名,固件不认 → 直接加载 grub 会被拒绝。

shim 的由来与作用:微软为第三方发行版开的"前门"(GPL,Red Hat 维护,微软 UEFI CA 签名):

固件(信任:微软 UEFI CA)→ shimaa64.efi(微软 CA 签,全主板都认)
       → shim 内嵌发行版 CA key(Canonical)→ 验签加载 grubaa64.efi
       → grub 经 shim 验证接口(shim lock)验签加载 vmlinuz

本机实测(Secure Boot 关闭,shim 退化为直通):

efibootmgr -v
# BootCurrent: 0004
# Boot0004* ubuntu   → File(\EFI\ubuntu\shimaa64.efi)          ← 当前(Ubuntu 安装器固定以 shim 开链)
# Boot0002* Uefi Debian Grub Boot → File(\EFI\debian\grubaa64.efi)  ← 裸 grub 入口(SB 开启后将失效)

sudo mokutil --sb-state              # SecureBoot disabled(本机)
sudo dmesg | grep -iE "secureboot|secure boot" | head
ls /boot/efi/EFI/ubuntu/             # shimaa64.efi / grubaa64.efi / grub.cfg
cat /boot/efi/EFI/ubuntu/grub.cfg    # 实际指向 /boot/grub/grub.cfg

Secure Boot 查看/管理相关命令速查:

# —— 查看 ——
mokutil --sb-state                            # enabled / disabled
efibootmgr -v                                 # 启动条目、BootCurrent、TimeOut
dmesg | grep -iE "secureboot|secure boot"     # 内核声明
cat /sys/firmware/efi/efivars/SecureBoot-*    # 原始变量(8 字节,末尾 ff 为开)

# —— 管理(建议手动在固件 UI 改,命令行仅作应急)——
sudo efibootmgr -o 0004,0002,0000,0001        # 调整 BootOrder
sudo efibootmgr -n 0004                       # 一次性 BootNext(下次启动有效)
sudo efibootmgr -b 0004 -n                    # 临时禁用某条目(加回用 -a)
sudo mokutil --import <my-key>.der            # 导入 MOK(重启后在 MOK 界面确认/输入口令)
sudo mokutil --list-enrolled                  # 已导入的自签密钥
sudo mokutil --disable-validation             # 关闭 shim 对内核的验证(草率,不推荐)

# —— 安装/重建引导(确认签名链)——
sudo grub-install --efi-directory=/boot/efi --bootloader-id=ubuntu
sudo update-grub                               # 或 grub2-mkconfig -o /boot/grub/grub.cfg

⚠️ 本机 cmdline 没有 console=,内核控制台来自 DTB stdout-path(串口)——这正是"IPMI 视频只有 EFI 三行、串口才有内核日志"的机制来源。

7.2 为什么重启后停在 BusyBox?—— initramfs 的"临时用户态"

完整启动阶段:

UEFI 固件(Boot0004)→ shim → grub(菜单 10s)→ vmlinuz/initrd.img
  → 内核:CPU/内存/驱动初始化(日志 CPU53-57 Booted,约 20s)
  → 解压 initramfs 为 / 上的 tmpfs → 执行 /init(initramfs-tools 的 shell 脚本)  ← 已进入"用户态①"
  → /init:加载驱动 → 挂载根盘前先做 fsck 检查
  → fsck.ext4 -a 发现 UNEXPECTED INCONSISTENCY(roots: -a 不自动修,exit 4)
  → 判"根文件系统需要人工 fsck" → drop 到 BusyBox ash:(initramfs)  ← 用户态① 的救援 shell
  → (人工 fsck 修复后 reboot →)再走一遍:挂根盘 → systemd → 完整用户态② → 网络

要点:

相关命令:

# —— 查看 initramfs 内部(无需启动)——
lsinitramfs /boot/initrd.img-$(uname -r) | head -30      # 列出镜像目录树
unmkinitramfs /boot/initrd.img-5.15.0-107-generic /tmp/ird   # 解包到目录
zcat /boot/initrd.img-* | cpio -it | grep -i busybox      # 找 busybox

# —— 调试用启动参数(临时改 grub 菜单的 linux 行,按 e 编辑)——
# rdinit=/bin/bash          # 跳过 init 脚本直达 bash(最后手段)
# init=/bin/bash            # 根盘挂载后直接 bash
# console=ttyS0,115200      # 强制串口(本机虽无 console=,DTB 已指向串口)

# —— fsck 相关(发现/修复状态)——
tune2fs -l /dev/sda2 | grep -E "Filesystem state|Errors behavior|Last checked"
e2fsck -n /dev/sda2        # dry-run 预检;-fy 实际修复;-a 自动模式(不处理不一致)

7.3 串口/SOL 常见 FAQ(实操细节)

Q1:物理串口和 IPMI SOL 只能有一个激活吗? 对。BMC 里 SYS COM 的信号一次只能接一个出口(面板 / BMC 本地 / SOL 网络),serialdir 方向值 0(面板)与 2(SOL)互斥。不是权限限制,是这套物理 mux 的机械事实——同一根"串口线"总得先连到一个地方。

Q2:iBMC 是"四口串口交换机"是什么意思?内核知道输出去了哪吗? serialdir 不是软件层面"关联 ttyS0",而是硬件/电气层面的切换(TX/RX 走线进 BMC 的多路选择器)。ttyS0 = 主板 UART 芯片(16550A @MMIO 0x3f00002f8),内核/grub 完全不知道信号被接到面板还是 SOL——它只对芯片寄存器读写,连到哪是 BMC 的 mux 决定的;一次一路,切换方向不影响内核。

Q3:CLP 是什么? Huawei iBMC 的 CLP = Command Line Protocol:ssh Administrator@<bmc-ip> 登录后看到的 iBMC:/> shell(命令:ipmcget/ipmcset/ping…)。它管理 BMC 自己,与服务器内核串口是两条赛道——这就是为什么它没有 sol 命令、也进不了串口终端。

Q4:已有串口输出,为什么还要加 console=?加了 VGA 就有画面了吗? console= 的含义是"告诉内核注册哪些终端作为控制台"。无该参数时内核按 ACPI SPCR 自动注册 ttyS0(串口收日志)→ VGA 无输出。加:

console=ttyS0,115200 console=tty0

是新增第二个输出目标 tty0(VGA/efifb 虚拟终端)——内核支持多控制台并存,一条 printk 广播给已注册的每个 console:串口照旧,VGA 同步滚同一份日志。规则:第一个 console= 为主通道,最后一个为 /dev/console(登录终端);只写 console=ttyS0 行为与现在一样(还是只有串口)。

Q5:serialdir -v 2 后 printk 就到 SOL 了;那 ipmitool sol activate 是干嘛的?ssh 登录 BMC 看得到吗?

Q6:ipmcget -d systemcom 和 sftp 两条命令分别在哪里执行?

ipmcget -d systemcom        # ① 在 ssh 登录 iBMC 之后执行(CLP 的 iBMC:/> 提示符里)
                            #    作用:BMC 把最近 2MB 串口环回数据打包到 BMC 本地 /tmp/systemcom.tar
sftp Administrator@<bmc-ip> # ② 在自己电脑的终端执行
                            #    作用:SFTP 登录 BMC,把 /tmp/systemcom.tar 下回本机

顺序:先 ① 生成包,再 ② 拉取解析。

7.4 IPMI SOL 必须认证吗?安全加固怎么做

必须认证——实测错误密码:

ipmitool -I lanplus -H 192.168.6.100 -U Administrator -P wrongpass manual
# Error: Unable to establish IPMI v2 / RMCP+ session

原理:SOL 走 RMCP+ 会话,用户名+密码认证(iBMC 用户表,与 Web/SSH 同一套);

风险面:SOL 认证通过 = 能看到内核串口、往里敲命令、外加远程电源管理——最高权限运维通道。加固清单:

# —— 检查/调整(iBMC Web UI)——
# 服务管理 → 端口服务       :禁用 IPMI over LAN(UDP 623),平时只用 Web/SSH,需要 SOL 时再开
# 用户&安全 → 安全配置       :IP 访问白名单(只允许管理网段)、登录失败锁定、会话超时
# 用户&安全 → 本地用户       :密码复杂度策略保持开启,不用弱口令
# —— 会话收尾 ——
ipmitool -I lanplus -H <bmc-ip> -U Administrator sol deactivate   # 主动释放独占会话

八、总结

  1. 根分区只读 ≠ 盘死了:读 dmesg 的块层错误 + ext4 aborted journal + e2fsck -n,先定位到"fsck 可解"的层次;只有 SMART/持续 I/O 错误才说明硬件报废。
  2. initramfs 的 (initramfs) 提示符是"等着你"不是"死了":fsck.ext4 -a 遇 UNEXPECTED INCONSISTENCY 不会自动修;手动 -fy 20 秒收工。
  3. IPMI KVM 只投 VGA:鲲鹏服务器要点"串口控制台"(SOL/采集包/物理串口)才看得到内核;iBMC 3.03 无 SOL 命令时还有三招——串口方向 serialdir、systemcom 采集包、LAN SOL(ipmitool)。
  4. 生产服务器磁盘该进 RAID/有备份:/dev/sda 单盘直连是脆弱点,本次坏一个扇区就差点放倒整台机器。