跳转至

varified_rootfs_ok.sh - RootFS 验证和补全脚本详解

脚本概述

varified_rootfs_ok.sh 是 IMX-Forge 项目中用于验证和补全根文件系统(Rootfs)的关键脚本。它确保构建的 Rootfs 具备完整的目录结构、配置文件和基础设备节点,使系统能够正常启动和运行。

核心功能

  • 目录结构验证:检查必需的目录是否存在(bin、sbin、usr)
  • 目录自动创建:补全缺失的标准目录结构
  • 配置文件生成:自动创建 fstab、inittab、rcS 等关键配置
  • 设备文件支持:创建 linuxrc 初始化链接
  • 第三方扩展:执行 third_party_install 目录下的安装脚本
  • 完整性验证:最终验证 Rootfs 是否可用

设计理念

Rootfs 是嵌入式 Linux 系统的"最后一公里"。即使内核成功编译并启动,如果 Rootfs 不完整,系统也无法正常运行。常见问题包括:

  • 缺少必需的目录导致程序找不到路径
  • 缺少配置文件导致 init 无法启动
  • 缺少库文件导致动态链接程序无法运行
  • 设备节点缺失导致硬件访问失败

这个脚本的设计遵循"先验证,后补全"的原则。它首先检查 Rootfs 是否具备基本条件,然后自动补全缺失的部分,最后验证完整性。这种设计确保开发者在早期就能发现问题,而不是等到板子启动失败时才排查。

在构建流程中的位置

build-busybox.sh (编译 BusyBox)
   安装到 rootfs/nfs/
varified_rootfs_ok.sh (验证和补全)
    Rootfs 就绪
  通过 NFS 启动开发板

脚本通常在 BusyBox 安装完成后执行,也可以在修改 Rootfs 后手动运行以验证完整性。

依赖关系

varified_rootfs_ok.sh
    ├─ scripts/lib/logging.sh (日志工具库)
    ├─ scripts/third_party_install/*.sh (第三方安装脚本)
    └─ rootfs/nfs/ (目标 Rootfs 目录)

参数说明

命令行参数

./scripts/varified_rootfs_ok.sh [OPTIONS]
参数 说明 必需/可选
--rootfs-dir=PATH 指定 Rootfs 目录路径 可选(默认:rootfs/nfs)
--rootfs-dir PATH 指定 Rootfs 目录路径(空格分隔) 可选
--help, -h 显示帮助信息 可选

环境变量

变量 说明 默认值
ROOTFS_DIR Rootfs 目录路径 PROJECT_ROOT/rootfs/nfs
DEBUG 启用调试输出 0
CROSS_COMPILE 交叉编译器前缀 arm-none-linux-gnueabihf-

第三方安装脚本环境变量

脚本执行第三方安装时,会传递以下环境变量:

变量 说明
ROOTFS_DIR Rootfs 目录的绝对路径
PROJECT_ROOT 项目根目录的绝对路径

使用方法

基本用法

# 使用默认 rootfs/nfs 目录
./scripts/varified_rootfs_ok.sh

# 指定自定义 Rootfs 目录
./scripts/varified_rootfs_ok.sh --rootfs-dir=/path/to/rootfs

# 使用相对路径
./scripts/varified_rootfs_ok.sh --rootfs-dir=rootfs/custom

典型使用场景

场景 1:BusyBox 编译后自动执行

build-busybox.sh 完成后,脚本自动补全 Rootfs:

# 编译 BusyBox(包含安装步骤)
./scripts/build_helper/build-busybox.sh

# 手动执行验证(或集成到构建脚本)
./scripts/varified_rootfs_ok.sh

场景 2:修改 Rootfs 后重新验证

# 添加自定义文件到 rootfs
cp my_app rootfs/nfs/usr/bin/

# 验证 Rootfs 仍然完整
./scripts/varified_rootfs_ok.sh

场景 3:使用不同的 Rootfs 目录

# 为测试创建独立的 Rootfs
mkdir -p rootfs/test
cp -r rootfs/nfs/* rootfs/test/

# 验证测试版本
./scripts/varified_rootfs_ok.sh --rootfs-dir=rootfs/test

输出示例

[INFO] ========================================
[INFO] RootFS Verification and Completion
[INFO] ========================================
[INFO] Rootfs directory: /home/user/imx-forge/rootfs/nfs
[INFO] Cross compiler:   arm-none-linux-gnueabihf-gcc
[INFO]
[INFO] Step 1: Safety checks...
[INFO]   Directory is safe
[INFO]
[INFO] Step 2: Verifying required directories...
[INFO] Found required directories: bin sbin usr
[INFO]   All required directories present
[INFO]
[INFO] Step 3: Creating directory structure...
[INFO] Creating rootfs directory structure...
[DEBUG]   Exists: bin
[DEBUG]   Creating: dev
[DEBUG]   Exists: etc
[DEBUG]   Creating: lib
[INFO] Creating linuxrc -> bin/busybox symlink
[INFO] Rootfs directory structure created
[INFO]
[INFO] Step 4: Creating configuration files...
[INFO] Creating etc/fstab...
[INFO]   Created: /home/user/imx-forge/rootfs/nfs/etc/fstab
[INFO] Creating etc/init.d/rcS...
[INFO]   Created: /home/user/imx-forge/rootfs/nfs/etc/init.d/rcS (executable)
[INFO] Creating etc/inittab...
[INFO]   Created: /home/user/imx-forge/rootfs/nfs/etc/inittab
[INFO]
[INFO] Step 5: Running third-party installations...
[INFO]   Executing: install_libc.sh
[INFO]     Found toolchain library directory: /usr/arm-none-linux-gnueabihf/lib
[INFO]     Copied 45 library files to lib/
[INFO]     Copied 12 library files to usr/lib/
[INFO]     install_libc.sh completed
[INFO] Third-party installations completed
[INFO]
[INFO] Step 6: Verifying completion...
[DEBUG]   bin/ exists
[DEBUG]   dev/ exists
[DEBUG]   etc/ exists
...
[INFO]   etc/fstab exists
[INFO]   etc/init.d/rcS exists
[INFO]   etc/inittab exists
[INFO] Rootfs verification passed
[INFO]
[INFO] ========================================
[INFO] RootFS completed successfully!
[INFO] ========================================
[INFO]
[INFO] Your rootfs is ready at: /home/user/imx-forge/rootfs/nfs
[INFO]
[INFO] To use this rootfs:
[INFO]   1. Export via NFS: /home/user/imx-forge/rootfs/nfs
[INFO]   2. Set bootargs to mount NFS root
[INFO]   3. Boot your board

执行流程

总体架构

脚本的执行流程分为六个阶段:

┌─────────────────────────────────────────────────────────────┐
│  1. 初始化阶段                                               │
│     - 解析命令行参数                                         │
│     - 设置默认 rootfs 目录                                   │
│     - 加载日志库                                             │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│  2. 安全检查阶段                                             │
│     - check_directory_safe()                                 │
│       ├─ 检查是否为 "/"                                      │
│       └─ 检查解析后是否为 "/"                                │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│  3. 必需目录验证                                             │
│     - check_required_dirs()                                  │
│       ├─ 检查 bin、sbin、usr 是否存在                        │
│       └─ 缺失时报错退出                                      │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│  4. 目录结构创建                                             │
│     - create_rootfs_structure()                              │
│       ├─ 创建所有标准目录                                    │
│       └─ 创建 linuxrc 符号链接                              │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│  5. 配置文件生成                                             │
│     ├─ create_fstab()     (文件系统挂载表)                   │
│     ├─ create_rcs()       (系统初始化脚本)                   │
│     └─ create_inittab()   (init 进程配置)                    │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│  6. 第三方扩展安装                                           │
│     - run_third_party_installs()                             │
│       └─ 执行 scripts/third_party_install/*.sh               │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│  7. 完整性验证                                               │
│     - verify_rootfs()                                        │
│       └─ 检查所有目录和文件是否完整                          │
└─────────────────────────────────────────────────────────────┘

函数详解

check_directory_safe()

作用:防止脚本误操作系统根目录。

安全机制

# 检查 1:路径是否恰好是 "/"
if [[ "$dir" == "/" ]]; then
    log_error "Rootfs directory cannot be '/'"
    return 1
fi

# 检查 2:解析后的绝对路径是否是 "/"
abs_dir="$(cd "$dir" 2>/dev/null && pwd)"
if [[ "$abs_dir" == "/" ]]; then
    log_error "Rootfs directory resolves to '/' (unsafe)"
    return 1
fi

为什么需要这个检查

Rootfs 验证脚本会创建目录、修改文件。如果误将 rootfs 目录指定为系统根目录,会破坏主机系统。这个检查提供了基本的安全保护。

check_required_dirs()

作用:验证 Rootfs 是否具备基本条件。

必需目录

REQUIRED_DIRS=("bin" "sbin" "usr")

检查逻辑

for dir in "${REQUIRED_DIRS[@]}"; do
    if [[ -d "${rootfs}/${dir}" ]]; then
        found+=("$dir")
    else
        missing+=("$dir")
    fi
done

if [[ ${#missing[@]} -gt 0 ]]; then
    log_error "Missing required directories: ${missing[*]}"
    return 1
fi

为什么检查这三个目录

  • /bin:存放基本命令(BusyBox 链接)
  • /sbin:存放系统管理命令
  • /usr:存放用户程序和库

如果这三个目录不存在,说明 BusyBox 没有正确安装,Rootfs 无法使用。

create_rootfs_structure()

作用:创建标准的 Rootfs 目录结构。

创建的目录

ROOTFS_DIRS=("bin" "dev" "etc" "lib" "mnt" "proc" "root" "sbin" "sys" "tmp" "usr" "home")

目录用途对照

目录 用途 创建时机
bin 基本命令 BusyBox 安装时创建
sbin 系统命令 BusyBox 安装时创建
usr 用户程序 BusyBox 安装时创建
dev 设备文件 脚本创建
etc 配置文件 脚本创建
lib 共享库 脚本创建
proc 进程信息(虚拟) 脚本创建
sys 内核信息(虚拟) 脚本创建
tmp 临时文件 脚本创建
mnt 挂载点 脚本创建
root root 用户主目录 脚本创建
home 普通用户主目录 脚本创建

linuxrc 链接创建

if [[ ! -e "$linuxrc" ]]; then
    log_info "Creating linuxrc -> bin/busybox symlink"
    ln -sf bin/busybox "$linuxrc"
fi

linuxrc 是传统 Linux 的初始化程序路径。内核在启动时如果找不到 /sbin/init,会尝试执行 /linuxrc。通过创建这个符号链接,确保系统能够找到 BusyBox 的 init。

create_fstab()

作用:创建文件系统挂载表。

生成内容

#<file system>  <mount point>   <type>  <options>   <dump>  <pass>
proc            /proc           proc    defaults    0       0
tmpfs           /tmp            tmpfs   defaults    0       0
sysfs           /sys            sysfs   defaults    0       0

各字段含义

  • proc /proc proc:挂载 proc 虚拟文件系统(进程信息)
  • tmpfs /tmp tmpfs:挂载 tmpfs 到 /tmp(内存文件系统,减少 Flash 写入)
  • sysfs /sys sysfs:挂载 sysfs 虚拟文件系统(内核设备信息)

为什么使用 tmpfs

嵌入式系统通常使用 Flash 存储。频繁写入会缩短 Flash 寿命。将 /tmp 挂载为 tmpfs 可以:

  1. 减少对 Flash 的写入
  2. 提高临时文件访问速度
  3. 重启后自动清理

create_rcs()

作用:创建系统初始化脚本。

生成内容

#!/bin/sh
#
# System initialization script
#

PATH=/sbin:/bin:/usr/sbin:/usr/bin:$PATH
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib:/usr/lib
export LD_LIBRARY_PATH

# Mount all filesystems specified in fstab
mount -a

# Create and mount devpts for pseudo-terminal support
mkdir -p /dev/pts
mount -t devpts devpts /dev/pts

# Populate /dev with device nodes
mdev -s

脚本逐行解析

  1. PATH 设置:确保系统能找到常用命令
  2. LD_LIBRARY_PATH:指定动态库搜索路径
  3. mount -a:读取 /etc/fstab,挂载所有文件系统
  4. mkdir -p /dev/pts && mount -t devpts:挂载伪终端(SSH 等需要)
  5. mdev -s:扫描 /sys 目录并创建设备节点

关于 mdev

mdev 是 BusyBox 的设备管理器,相当于精简版的 udev。-s 选项表示"扫描"模式,在系统启动时创建所有已检测到的设备节点。

create_inittab()

作用:创建 init 进程配置文件。

生成内容

# /etc/inittab - init process configuration

# System initialization
::sysinit:/etc/init.d/rcS

# Console getty (askfirst = prompt before starting shell)
console::askfirst:-/bin/sh

# Restart handling
::restart:/sbin/init

# Ctrl+Alt+Del handling
::ctrlaltdel:/sbin/reboot

# Shutdown actions
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a

inittab 格式

<id>:<runlevels>:<action>:<process>

各行解析

action process 说明
sysinit sysinit /etc/init.d/rcS 启动时首先执行
console askfirst -/bin/sh 控制台 shell,启动前提示用户
restart restart /sbin/init init 重启时执行
ctrlaltdel ctrlaltdel /sbin/reboot Ctrl+Alt+Del 时重启
shutdown shutdown umount/swapoff 关机时卸载文件系统

askfirst 的作用

askfirst 会在启动 shell 前显示 "Please press Enter to activate this console.",让用户有时间看到启动信息,避免日志被登录提示淹没。

run_third_party_installs()

作用:执行第三方安装脚本,扩展 Rootfs 功能。

查找脚本

find "$THIRD_PARTY_INSTALL_DIR" -maxdepth 1 -name "*.sh" -type f -print0 | sort -z

执行环境

export ROOTFS_DIR="$rootfs"
export PROJECT_ROOT="$PROJECT_ROOT"

bash "$script"

错误处理

if bash "$script"; then
    log_info "    $name completed"
else
    log_warn "    $name failed (continuing anyway)"
fi

即使某个脚本失败,也会继续执行其他脚本。这种设计允许部分功能失败而不影响整体流程。

典型第三方脚本

  1. install_libc.sh:复制工具链的库文件到 Rootfs
  2. install_openssl.sh:安装 OpenSSL 库(可能存在)
  3. custom_app.sh:安装自定义应用

verify_rootfs()

作用:最终验证 Rootfs 完整性。

验证项目

# 1. 检查目录
for dir in "${ROOTFS_DIRS[@]}"; do
    if [[ -d "${rootfs}/${dir}" ]]; then
        log_debug "  ${dir}/ exists"
    else
        log_error "  ${dir}/ missing"
        all_ok=0
    fi
done

# 2. 检查 linuxrc
if [[ -e "${rootfs}/linuxrc" ]]; then
    log_debug "  linuxrc exists"
fi

# 3. 检查配置文件
config_files=("etc/fstab" "etc/init.d/rcS" "etc/inittab")
for file in "${config_files[@]}"; do
    if [[ -f "${rootfs}/${file}" ]]; then
        log_debug "  ${file} exists"
    else
        log_error "  ${file} missing"
        all_ok=0
    fi
done

验证标准

类别 项目 必需性
目录 bin, sbin, usr, dev, etc, lib, proc, sys, tmp, mnt, root, home 必需
链接 linuxrc 推荐
配置 etc/fstab 必需
配置 etc/init.d/rcS 必需
配置 etc/inittab 必需

Rootfs 完整性标准

必需的目录结构

一个最小但完整的 Rootfs 必须具备以下目录:

rootfs/nfs/
├── bin/           # 基本命令(BusyBox 及符号链接)
├── sbin/          # 系统管理命令
├── usr/           # 用户程序和库
│   └── lib/       # 用户库文件
├── lib/           # 共享库文件
├── etc/           # 配置文件
│   ├── fstab      # 文件系统挂载表
│   ├── inittab    # init 配置
│   ├── init.d/    # 启动脚本目录
│   │   └── rcS    # 系统初始化脚本
│   ├── profile    # Shell 环境配置
│   ├── passwd     # 用户数据库
│   └── group      # 用户组数据库
├── dev/           # 设备文件(mdev 创建)
├── proc/          # proc 文件系统挂载点
├── sys/           # sysfs 文件系统挂载点
├── tmp/           # 临时文件(tmpfs)
├── mnt/           # 临时挂载点
├── root/          # root 用户主目录
└── home/          # 普通用户主目录

必需的配置文件

/etc/fstab

#<file system>  <mount point>   <type>  <options>   <dump>  <pass>
proc            /proc           proc    defaults    0       0
tmpfs           /tmp            tmpfs   defaults    0       0
sysfs           /sys            sysfs   defaults    0       0
devpts          /dev/pts        devpts  defaults    0       0

/etc/inittab

# System initialization
::sysinit:/etc/init.d/rcS

# Console getty
console::askfirst:-/bin/sh

# Restart handling
::restart:/sbin/init

# Ctrl+Alt+Del handling
::ctrlaltdel:/sbin/reboot

# Shutdown actions
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a

/etc/init.d/rcS

#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:$PATH
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib:/usr/lib
export LD_LIBRARY_PATH

mount -a
mkdir -p /dev/pts
mount -t devpts devpts /dev/pts
mdev -s

设备文件说明

对于支持 devtmpfs 的内核(2.6.32+),内核会自动创建大部分设备文件。对于最小化配置的内核,可能需要手动创建基础设备节点:

设备 主设备号 次设备号 用途
/dev/console 5 1 系统控制台
/dev/null 1 3 空设备
/dev/zero 1 5 零设备
/dev/random 1 8 随机数发生器
/dev/urandom 1 9 非阻塞随机数
/dev/tty 5 0 控制终端
/dev/tty0 4 0 虚拟终端 0

使用 mdev -s 可以自动创建这些设备节点。

配置选项

硬编码配置

# 交叉编译器
CROSS_COMPILE=arm-none-linux-gnueabihf-

# 必需目录
REQUIRED_DIRS=("bin" "sbin" "usr")

# 所有目录
ROOTFS_DIRS=("bin" "dev" "etc" "lib" "mnt" "proc" "root" "sbin" "sys" "tmp" "usr" "home")

# 默认 rootfs 目录
ROOTFS_DIR="${PROJECT_ROOT}/rootfs/nfs"

# 第三方安装脚本目录
THIRD_PARTY_INSTALL_DIR="${SCRIPT_DIR}/third_party_install"

自定义配置

修改默认 Rootfs 目录

编辑脚本中的默认值:

# 修改这一行
: "${ROOTFS_DIR:=${PROJECT_ROOT}/rootfs/nfs}"

# 改为
: "${ROOTFS_DIR:=${PROJECT_ROOT}/rootfs/custom}"

添加更多目录

修改 ROOTFS_DIRS 数组:

ROOTFS_DIRS=("bin" "dev" "etc" "lib" "mnt" "proc" "root" "sbin" "sys" "tmp" "usr" "home" "opt" "var")

修改配置模板

编辑 create_fstab()create_rcS()create_inittab() 函数中的内容。

故障排除

常见错误

错误 1:Rootfs directory cannot be '/'

[ERROR] Rootfs directory cannot be '/'

原因:错误地将 rootfs 目录指定为系统根目录。

解决方法

检查命令参数:

# 错误示例
./scripts/varified_rootfs_ok.sh --rootfs-dir=/

# 正确示例
./scripts/varified_rootfs_ok.sh --rootfs-dir=rootfs/nfs

错误 2:Missing required directories

[ERROR] Missing required directories: bin sbin usr

原因:BusyBox 未正确安装到 Rootfs。

解决方法

  1. 确认 BusyBox 已编译:
ls -l out/busybox/busybox
  1. 重新安装 BusyBox:
./scripts/build_helper/build-busybox.sh --install-only
  1. 或者手动检查目录:
ls -la rootfs/nfs/

错误 3:Cannot access directory

[ERROR] Cannot access directory: /path/to/rootfs

原因:指定的目录不存在或没有访问权限。

解决方法

  1. 创建目录:
mkdir -p /path/to/rootfs
  1. 检查权限:
ls -ld /path/to/rootfs

错误 4:配置文件已存在

脚本会覆盖现有的配置文件。如果需要保留自定义配置,可以:

  1. 备份现有配置:
cp rootfs/nfs/etc/inittab rootfs/nfs/etc/inittab.bak
  1. 执行脚本后恢复备份:
cp rootfs/nfs/etc/inittab.bak rootfs/nfs/etc/inittab
  1. 或者修改脚本,添加检查逻辑:
create_inittab() {
    local rootfs="$1"
    local inittab_file="${rootfs}/etc/inittab"

    if [[ -f "$inittab_file" ]]; then
        log_info "Preserving existing inittab"
        return 0
    fi

    # ... 原有创建逻辑
}

错误 5:第三方安装脚本失败

[WARN]     install_libc.sh failed (continuing anyway)

原因:第三方脚本执行失败,但不影响主流程。

解决方法

  1. 手动运行脚本查看详细错误:
cd scripts/third_party_install
ROOTFS_DIR=../../rootfs/nfs PROJECT_ROOT=../../ ./install_libc.sh
  1. 检查脚本依赖是否满足:
# 检查工具链
which arm-none-linux-gnueabihf-gcc

# 检查库目录
ls /usr/arm-none-linux-gnueabihf/lib

错误 6:验证失败

[ERROR]   bin/ missing
[ERROR] Rootfs verification failed

原因:验证阶段发现目录或文件缺失。

解决方法

  1. 检查目录是否被意外删除:
ls -la rootfs/nfs/
  1. 重新执行脚本创建缺失部分:
./scripts/varified_rootfs_ok.sh
  1. 如果问题持续,检查磁盘空间:
df -h

调试技巧

启用调试输出

DEBUG=1 ./scripts/varified_rootfs_ok.sh

手动验证 Rootfs

# 检查目录结构
find rootfs/nfs/ -type d | sort

# 检查配置文件
cat rootfs/nfs/etc/fstab
cat rootfs/nfs/etc/inittab

# 检查脚本权限
ls -l rootfs/nfs/etc/init.d/rcS

# 检查设备文件
ls -l rootfs/nfs/dev/

在板子上测试

将 Rootfs 通过 NFS 挂载后,检查:

# 在板子上执行
ls /
cat /etc/inittab
cat /proc/mounts

设计决策说明

为什么需要验证 Rootfs

Rootfs 的完整性直接影响系统能否启动。常见问题包括:

  1. 目录缺失:程序找不到路径
  2. 配置缺失:init 无法启动
  3. 库文件缺失:动态链接程序无法运行
  4. 设备节点缺失:硬件访问失败

通过验证和补全,可以在开发阶段就发现问题,避免到板子上调试。

为什么不使用 Buildroot

Buildroot 是完整的 Rootfs 构建系统,但它:

  1. 编译时间长(首次几小时)
  2. 配置复杂(1000+ 选项)
  3. 不适合学习和调试

IMX-Forge 的方案是:

  1. 使用 BusyBox 构建最小系统
  2. 使用脚本验证和补全
  3. 按需添加第三方组件

这种方式更透明、更可控,适合学习和理解原理。

为什么自动生成配置文件

手动创建配置文件容易出错,而且不同项目需要调整。自动生成的优点:

  1. 一致性:每次生成的配置相同
  2. 可维护:修改脚本即可更新所有配置
  3. 可定制:通过修改模板快速调整

为什么支持第三方安装脚本

不同的项目有不同的需求:

  1. 某些项目需要 OpenSSL
  2. 某些项目需要特定的库
  3. 某些项目需要自定义应用

通过 third_party_install 机制,可以在不修改主脚本的情况下扩展功能。

扩展和定制

添加自定义配置文件

在脚本中添加新的配置生成函数:

create_network_config() {
    local rootfs="$1"
    local interfaces_file="${rootfs}/etc/network/interfaces"

    log_info "Creating network configuration..."

    cat > "$interfaces_file" << 'EOF'
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp
EOF

    log_info "  Created: $interfaces_file"
}

# 在 main() 函数中调用
main() {
    # ...
    create_fstab "$ROOTFS_DIR"
    create_rcs "$ROOTFS_DIR"
    create_inittab "$ROOTFS_DIR"
    create_network_config "$ROOTFS_DIR"  # 新增
    # ...
}

创建第三方安装脚本

scripts/third_party_install/ 目录创建新脚本:

#!/bin/bash
#
# install_mylib.sh - Install custom library
#

set -e

GREEN='\033[0;32m'
NC='\033[0m'
log_info() { echo -e "${GREEN}[install_mylib]${NC} $1"; }

# 使用主脚本传递的环境变量
: "${ROOTFS_DIR:=../rootfs/nfs}"
: "${PROJECT_ROOT:=..}"

log_info "Installing mylib to: ${ROOTFS_DIR}"

# 创建目录
mkdir -p "${ROOTFS_DIR}/usr/lib"

# 复制库文件
cp "${PROJECT_ROOT}/build/libmylib.so" "${ROOTFS_DIR}/usr/lib/"

log_info "Installation complete"

修改 fstab 模板

编辑 create_fstab() 函数:

create_fstab() {
    local rootfs="$1"
    local fstab_file="${rootfs}/etc/fstab"

    cat > "$fstab_file" << 'EOF'
#<file system>  <mount point>   <type>  <options>   <dump>  <pass>
proc            /proc           proc    defaults    0       0
tmpfs           /tmp            tmpfs   defaults    0       0
sysfs           /sys            sysfs   defaults    0       0
devpts          /dev/pts        devpts  mode=0620  0       0
# 添加 NFS 挂载(示例)
192.168.1.100:/share /mnt/nfs nfs defaults  0       0
EOF

    log_info "  Created: $fstab_file"
}

添加验证项目

编辑 verify_rootfs() 函数:

verify_rootfs() {
    local rootfs="$1"

    log_info "Verifying rootfs completion..."

    local all_ok=1

    # 原有验证...

    # 新增:检查自定义配置
    local custom_configs=("etc/network/interfaces" "etc/hosts")
    for file in "${custom_configs[@]}"; do
        if [[ -f "${rootfs}/${file}" ]]; then
            log_debug "  ${file} exists"
        else
            log_warn "  ${file} missing (optional)"
        fi
    done

    # ...
}

相关文档

更新日志

日期 版本 更新内容
2026-03-15 1.0 初始完整版本

文档生成时间: 2026-03-15 对应脚本版本: commit 409a759