fnOS 1.2.0xx 升级踩坑记录

fnOS 1.2.0xx 升级踩坑记录

__

fnOS 1.2.0xx 升级踩坑记录:内核 initrd 生成失败导致存储卷挂载失败 / Docker 崩溃

设备环境

  • 硬件:OrangePi 5 Plus (RK3588),ARM64

  • 引导方式:Armbian / U-Boot

  • 存储:eMMC 系统盘 + NVMe,两个 RAID1 + LVM 卷(/vol1、/vol2)

  • 升级路径:此前系统一直卡在重复更新提示(大约在 1.1.31 之后的某个版本,具体版本号记不清了),后来官方发布过一次修复版本,修好之后版本号显示为 1.1.31xx。这次从 1.1.31xx 升级到 1.2.0xx(首次失败)→ 点击"系统修复"后回滚,版本号显示 1.1.19 → 再次升级到 1.2.0100(第二次,最终手动修复成功)

现象

  1. 系统更新界面提示 linux-image-6.18.18.c821-trim 一直无法完成更新

  2. 点击"系统修复"后,Web 端显示修复成功,但:

    • 原本自动挂载的存储卷(/vol1、/vol2)挂载失败,提示"系统内部错误"

    • Docker 服务反复重启失败,报错 mkdir /vol1/docker: operation not permitted

  3. dmesg 中持续刷屏:

    btrfs: Unknown parameter 'trimacl'ext4: Unknown parameter 'trimacl'
    

根因排查过程

第一步:确认这是本次 v1.2 权限机制升级引入的新参数

trimacl 是 fnOS 1.2.x 引入 Windows ACL 权限机制后,用户态挂载调用新增的 btrfs/ext4 挂载参数,需要配套的新内核才能识别。旧内核完全不认识这个参数,一旦用户态程序(trim 主程序)用这个参数发起挂载,必然失败。

第二步:确认内核包本身没有真正装完整

uname -r                          # 实际运行的内核
dpkg -l | grep linux-image        # 已安装的内核包
ls -la /boot/ | grep c821         # 检查新内核相关文件是否齐全

第一次升级(1.2.0xx)dpkg.log 显示 linux-image-6.18.18.c821-trim 卡在 half-configured 长时间不动,最终点击"系统修复"后该内核包被完全移除、系统回滚到 1.1.19。

第二次升级(1.2.0100)dpkg.log 显示内核包这次顺利装到 status installedtrim 主程序也升级到 1.2.0100,但检查 /boot 发现:

config-6.18.18.c821-trim      ✔ 存在
System.map-6.18.18.c821-trim  ✔ 存在
vmlinuz-6.18.18.c821-trim     ✔ 存在
initrd.img-6.18.18.c821-trim  ✘ 缺失!
uInitrd-6.18.18.c821-trim     ✘ 缺失!

第三步:定位 initrd 生成失败的真正原因

手动尝试生成 initrd:

/usr/sbin/update-initramfs -c -k 6.18.18.c821-trim

报错:

/usr/sbin/update-initramfs: 142: mkinitramfs: not found
update-initramfs: failed for /boot/initrd.img-6.18.18.c821-trim with 127

排查发现 mkinitramfs 文件其实存在dpkg -L initramfs-tools 能查到,find 也能找到),问题出在当前 shell 的 $PATH 环境变量里没有 /usr/sbin,导致 update-initramfs 脚本内部用裸命令名调用 mkinitramfs 时找不到。

结论:这是 fnOS 官方升级流程本身的 bug——升级脚本在执行到生成 initramfs 这一步时,运行环境的 PATH 不完整,导致 mkinitramfs 调用静默失败(不会让整个 dpkg 安装报错,只是这一步没有真正执行),最终内核包"看起来装完了"但实际上是个没有配套 initrd 的残缺内核。

第四步:发现引导方式的额外陷阱(ARM 设备特有)

一开始按常规思路修复 GRUB(grub-mkconfiggrub-reboot、改 grubenv),改完重启后 uname -r 依然是旧内核,毫无效果。进一步排查发现:

这台 ARM 设备实际走的是 Armbian 的 boot.scr / U-Boot 引导流程,不读取 GRUB 配置,真正生效的是 /boot/extlinux/extlinux.conf.bak 里写死的两个固定文件名:

LINUX /Image
INITRD /uInitrd

而当时 /boot/Image 这个符号链接从 5 月 16 日起就没再更新过,一直指向旧内核,导致不管新内核包装得多完整、GRUB 配置改得多对,U-Boot 启动时根本没看见新内核。

最终修复步骤

# 1. 用带完整 PATH 的方式手动生成 initrd(绕过升级脚本的 PATH bug)
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
  /usr/sbin/update-initramfs -c -k 6.18.18.c821-trim

# 2. 确认 initrd 生成成功
ls -la /boot/ | grep c821

# 3. 关键一步:修正 U-Boot 实际读取的两个符号链接(不是改 GRUB!)
ln -sf vmlinuz-6.18.18.c821-trim /boot/Image
ln -sf uInitrd-6.18.18.c821-trim /boot/uInitrd

# 4. 重启
reboot

重启后验证:

uname -r                     # 6.18.18.c821-trim ✔
dmesg -T | grep -i trimacl   # 无输出,参数已被新内核识别 ✔
lsblk                        # /vol1 /vol2 正常出现挂载点 ✔
mount | grep -i vol          # 挂载参数正确带上 trimacl 且无报错 ✔
systemctl status docker      # active (running) ✔

Docker 服务恢复后,个别容器需要在 1Panel 面板里手动重启一下才能完全恢复正常。

给同样踩坑用户的建议

  1. 升级前先确认自己的设备引导方式:如果 /boot 下能看到 boot.scrextlinux.conf.bak,说明是 Armbian/U-Boot 引导(常见于 ARM 设备),排查思路和改 GRUB 完全不同,不要在 GRUB 配置上浪费时间。

  2. 如果升级后出现 Unknown parameter 'trimacl' 报错、存储卷挂载失败、Docker 起不来,先检查 /boot 下新内核的 initrd/uInitrd 是否存在,大概率是没生成。

  3. 数据本身通常是安全的,可以用 mount -t btrfs /dev/mapper/xxx /mnt/test 手动只读挂载验证,不用过度紧张。

  4. 强烈建议 fnOS 官方修复升级脚本里生成 initramfs 步骤的 PATH 环境问题,这个 bug 在两次连续的更新包(1.2.0xx)里都复现了,怀疑所有 ARM 设备升级到 v1.2.x 都会遇到同样的问题。


排查环境:OrangePi 5 Plus (RK3588),Armbian/U-Boot 引导,供社区参考。具体操作请结合自己设备情况谨慎执行,操作前建议先确认数据可通过手动挂载访问。

Obsidian Self-hosted LiveSync 部署记录 2026-06-22

评论区