崇子顺
发布于 2025-09-27 / 48 阅读
2
0

极限操作:手动升级 OpenWrt/ImmortalWrt 根文件系统和内核(非官方方法)

警告: 这篇教程介绍的方法是在系统运行时直接替换关键系统文件,包括内核和整个根文件系统。这是一个高风险操作,可能导致系统崩溃、数据丢失或无法启动。请确保您了解其风险,并已备份所有重要配置。官方推荐使用 sysupgrade 工具。

一、前言:为何选择手动升级?

在标准的 OpenWrt/ImmortalWrt 升级流程中,我们通常使用 sysupgrade 命令。然而,对于某些特殊的 x86/64 部署环境或特定的定制需求,您可能需要手动控制文件替换的每一个步骤,例如在双分区或特殊引导配置下。

本文将为您提供一个 Shell 脚本,用于实现手动升级根文件系统和内核。

二、手动升级脚本

将以下代码保存为 /root/manual_upgrade.sh,并给予执行权限:chmod +x /root/manual_upgrade.sh。

#!/bin/sh
# ----------------------------------------------------
# !!! 极高风险警告 !!!
# 在运行中的系统上直接覆盖根文件系统是高风险操作。
# 此脚本已包含兼容性修复和用户确认步骤。请务必提前备份重要数据。
# ----------------------------------------------------

# 函数:请求用户确认
confirm_action() {
    while true; do
        read -r -p "=> ${1} (y/N)? " response
        case "$response" in
            [yY][eE][sS]|[yY])
                return 0
                ;;
            [nN][oO]|[nN]|"")
                echo "操作已取消。"
                exit 1
                ;;
            *)
                echo "请输入 'y' 或 'n'."
                ;;
        esac
    done
}

# ====================================================
# 配置变量 (重要:请根据您的升级目标进行修改)
# ====================================================
# 目标发行版名称 (例如: openwrt, immortalwrt)
PROJECT="immortalwrt"
# 目标版本号 (例如: 24.10.3)
VERSION="24.10.3"
# 目标架构路径 (URL中使用: x86/64)
ARCH_PATH="x86/64"
# 目标架构名称 (文件名中使用: x86-64)
ARCH_NAME="x86-64"

# 构造 URL 和文件名
BASE_URL="https://downloads.${PROJECT}.org/releases/${VERSION}/targets/${ARCH_PATH}"
KERNEL_FILE="${PROJECT}-${VERSION}-${ARCH_NAME}-generic-kernel.bin"
ROOTFS_FILE="${PROJECT}-${VERSION}-${ARCH_NAME}-rootfs.tar.gz"
KERNEL_URL="${BASE_URL}/${KERNEL_FILE}"
ROOTFS_URL="${BASE_URL}/${ROOTFS_FILE}"

echo "----------------------------------------------------"
echo "目标版本信息: ${PROJECT} ${VERSION} (${ARCH_NAME})"
echo "内核下载链接: ${KERNEL_URL}"
echo "根文件系统下载链接: ${ROOTFS_URL}"
echo "----------------------------------------------------"

confirm_action "确认上述升级目标信息正确,并开始下载文件"

# ----------------------------------------------------
# 步骤 1: 导出用户安装的非内核模块软件包列表
# ----------------------------------------------------
# 仅保留用户手动安装的非内核模块和非基础系统包,以备后续重新安装。
opkg list-installed | \
    awk '{print $1}' | \
    grep -v '^kmod-' | \
    grep -v '^lib' | \
    grep -v '^base-files' > /root/user-packages.txt

echo "已导出用户软件包列表到 /root/user-packages.txt"


# ----------------------------------------------------
# 步骤 2 & 3: 下载文件并解压
# ----------------------------------------------------
cd /tmp
echo "正在下载文件..."
wget --no-check-certificate "${KERNEL_URL}"
wget --no-check-certificate "${ROOTFS_URL}"

mkdir -p /tmp/new_rootfs
echo "正在解压新的根文件系统..."
tar -xvzf "${ROOTFS_FILE}" -C /tmp/new_rootfs


# ----------------------------------------------------
# 步骤 4: 替换内核文件 (高风险操作)
# ----------------------------------------------------
echo "----------------------------------------------------"
confirm_action "警告:将替换 /boot/vmlinuz 内核文件。这将影响系统重启。是否继续"

# 备份旧版本内核文件
cp /boot/vmlinuz /boot/vmlinuz.old
echo "已备份旧内核到 /boot/vmlinuz.old"

# 覆盖新内核
cp "/tmp/${KERNEL_FILE}" /boot/vmlinuz
echo "新内核文件已复制到 /boot/vmlinuz"


# ----------------------------------------------------
# 步骤 5: 处理配置文件
# ----------------------------------------------------
# 删除新 rootfs 中的默认配置,以保留当前系统的配置 (假定旧配置兼容新版本)
echo "正在删除新 rootfs 中的默认配置文件..."
rm -rf /tmp/new_rootfs/etc/config
rm -f /tmp/new_rootfs/etc/passwd \
    /tmp/new_rootfs/etc/shadow \
    /tmp/new_rootfs/etc/group \
    /tmp/new_rootfs/etc/hostname \
    /tmp/new_rootfs/etc/hosts \
    /tmp/new_rootfs/etc/resolv.conf


# ----------------------------------------------------
# 步骤 6: 覆盖根文件系统 (最核心、最危险的步骤)
# ----------------------------------------------------
echo "----------------------------------------------------"
echo "!! 最终警告: 接下来将覆盖正在运行的系统文件。"
echo "!! 此过程不可逆,可能导致系统在运行时崩溃或无法启动。"
echo "----------------------------------------------------"
confirm_action "是否确认覆盖根文件系统 (将排除只读目录) 并继续升级"

echo "开始复制文件到根文件系统,排除只读/虚拟目录..."

# 排除目录列表。避免复制到只读的 SquashFS 基础层、虚拟文件系统或特殊的挂载点。
EXCLUDE_DIRS="dev proc sys tmp overlay rom mnt media boot"
EXCLUDE_FILE="/tmp/tar_excludes.txt"

# 1. 创建排除文件 (使用通配符来匹配目录下的所有内容,兼容 BusyBox tar -X)
echo "" > "${EXCLUDE_FILE}"
for dir in $EXCLUDE_DIRS; do
    echo "${dir}/*" >> "${EXCLUDE_FILE}" # 排除目录下的所有内容
    echo "${dir}" >> "${EXCLUDE_FILE}"   # 排除目录本身
done

# 2. 使用兼容 BusyBox 的 tar 命令进行复制。
# 打包 /tmp/new_rootfs 并排除列表中的目录,然后通过管道解压到 / 根目录。
# -p 选项用于保留文件权限。
tar -C /tmp/new_rootfs -cf - -X "${EXCLUDE_FILE}" . | tar -x -p -C /

echo "根文件系统文件覆盖完成。"

# 清理临时文件和目录
rm -f "${EXCLUDE_FILE}"
rm -rf /tmp/new_rootfs
rm -f "/tmp/${KERNEL_FILE}" "/tmp/${ROOTFS_FILE}"


# ----------------------------------------------------
# 步骤 7: 重新安装用户软件包 (兼容 BusyBox xargs)
# ----------------------------------------------------
echo "正在更新软件包列表并重新安装用户软件包..."
opkg update

# 重新安装导出的非内核模块软件包
if [ -s /root/user-packages.txt ]; then
    echo "正在重新安装用户软件包..."
    # 使用 cat 将文件内容通过管道传给 xargs,以兼容 BusyBox 的 xargs
    cat /root/user-packages.txt | xargs -r opkg install
else
    echo "用户软件包列表为空,跳过重新安装。"
fi
echo "用户软件包重新安装完成。"

# 清理 opkg 临时文件
rm -f /root/user-packages.txt


# ----------------------------------------------------
# 步骤 8: 完成并重启
# ----------------------------------------------------
echo "----------------------------------------------------"
echo "文件系统和内核替换完成。系统需要重启。"
echo "!!! 再次强调:重启后请立即手动安装所需的内核模块(kmod-),否则相关硬件功能可能失效。"
echo "----------------------------------------------------"
confirm_action "是否确认立即重启以完成升级过程"

reboot

三、脚本执行流程概览

  1. 配置与确认: 在脚本开头修改 PROJECTVERSION 变量,然后确认下载链接。

  2. 准备软件包列表: 脚本会记录您当前系统上所有非内核模块非基础文件的用户安装软件包,用于升级后重新安装。

  3. 下载与解压: 下载新的内核 (*-generic-kernel.bin) 和根文件系统 (*-rootfs.tar.gz),并解压根文件系统到 /tmp/new_rootfs

  4. 配置文件保留: 删除新根文件系统中的默认配置文件(如 /etc/config/etc/passwd 等),以保留您旧系统的配置。

  5. 替换内核: 备份旧内核并用新内核替换 /boot/vmlinuz

  6. 覆盖根文件系统: 使用 tar 命令,排除 /dev/proc/sys/rom 等只读或虚拟目录,将新的文件覆盖到根目录 (/)。

  7. 重新安装软件包: 更新 opkg 列表,然后重新安装在步骤 1 中导出的用户软件包。

  8. 重启: 提示用户确认后执行 reboot

四、重启后的关键善后工作

这是最重要的一步!

由于新内核的 ABI(应用程序二进制接口)与旧内核不兼容,您原先安装的所有内核模块(kmod-*)将无法在新系统上加载。

您必须在重启后执行以下操作:

  1. 连接网络: 确保您的网络接口(如果它们不依赖特殊的 kmod)可以正常工作。

  2. 安装内核模块: 根据您旧系统上的硬件功能,手动安装对应的内核模块。

例如,如果您之前安装了 USB 存储支持和 CIFS 文件系统:

codeBash

opkg update
opkg install kmod-usb-storage kmod-fs-cifs
# ... 其他您需要的 kmod 包

如果您的系统功能在重启后无法正常工作(例如 Wi-Fi 或某些网口),请根据您的硬件型号和功能搜索对应的 kmod-* 包名并进行安装。


评论