写在开头

经常搞 Liunx 的人都知道,文件系统是 Liunx 不可或缺的一部分,难免会遇到需要自己定制一个文件系统的情形,本篇文章就是讲述了基于 ubuntu_base 来定制一个文件系统的方法。

环境准备

  1. 如果想要构建的文件系统和构建时所用的平台不一样,则需要创建一个模拟环境,创建也很简单,安装 qemu-user-static 即可。例如apt install qemu-user-static
  2. 获取 ubuntu_base,直接从官网下载即可,如果访问异常就挂一个代理,至于版本选择,一般情况选新不选旧,但也要结合你的实际情况。

ubuntu

配置根文件系统

ubuntu-base-24.04.1-base-arm64 为例:

  1. 解压根文件系统: tar -xvf ubuntu-base-24.04.1-base-arm64 -C 目标文件夹
  2. 为根文件系统配置网络: cp /etc/resolv.conf ubuntu-base-24.04.1-base-arm64/etc/resolv.conf
  3. 更换 apt 的软件源: sudo vim ubuntu-base-24.04.1-base-arm64/etc/apt/source.list

    更换内容需要根据 ubuntu 版本 + 架构 共同决定,上网搜 ubuntu 版本 + 架构 更换软件源进行覆盖即可。

    需要注意的是 ubuntu 24.04 不再通过上述文件控制软件源,而是 /etc/apt/sources.list.d/ubuntu.sources,参考换源见这里

  4. 编写 mount 脚本,这里直接提供一个通用脚本:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    #!/bin/bash
    function mnt() {
    echo "MOUNTING"
    sudo mount -t proc /proc ${2}proc
    sudo mount -t sysfs /sys ${2}sys
    sudo mount -o bind /dev ${2}dev
    #sudo mount -t devpts -o gid=5,mode=620 devpts ${2}dev/pts
    sudo mount -o bind /dev/pts ${2}dev/pts
    sudo chroot ${2}
    }
    function umnt() {
    echo "UNMOUNTING"
    sudo umount ${2}proc
    sudo umount ${2}sys
    sudo umount ${2}dev/pts
    sudo umount ${2}dev
    }
    if [ "$1" == "-m" ] && [ -n "$2" ];
    then
    mnt $1 $2
    elif [ "$1" == "-u" ] && [ -n "$2" ];
    then
    umnt $1 $2
    else
    echo ""
    echo "Either 1'st, 2'nd or both parameters were missing"
    echo ""
    echo "1'st parameter can be one of these: -m(mount) OR -u(umount)"
    echo "2'nd parameter is the full path of rootfs directory(with tralling '/')"
    echo ""
    echo "For example: ch-mount -m /media/sdcard"
    echo ""
    echo 1st parameter : ${1}
    echo 2nd parameter : $[2]
    fi

    此脚本目的是为了暂时将构建机所用的文件系统暂时切换到根文件系统,然后就可以像操作正常的文件系统一样为此文件系统安装软件包。

    用法如下:

    1
    2
    3
    4
    5
    6
    7
    8
    #增加脚本执行权限
    sudo chmod +x mount.sh
    #挂载根文件系统
    ./mount -m ubuntu_rootfs/
    #退出根文件系统
    exit
    #卸载根文件系统
    ./mount.sh -u ubuntu_rootfs/
  5. 挂载根文件系统,为其安装必要组件 + 按需自己安装

    1
    2
    3
    4
    5
    6
    #更新软件
    apt update
    apt upgrade
    #安装必要工具
    apt install vim bash-completion net-tools iputils-ping ifupdown ethtool \
    ssh rsync udev htop rsyslog nfs-common language-pack-en-base sudo psmisc
  6. 更改 root 密码,passwd root 按照提示输入两次密码即可。

    如果这里出现了 passwd:Authentication token manipulation error 这样的报错,可以参照这里解决。但是不一定能完美解决,如果实在改不了密码,可以使用下一步骤曲线救国:

  7. 设置自动登录 root 账户,在安装了 udev 后,可以打开 vi /lib/systemd/system/serial-getty\@.service,将 ExecStart 这一行改为 ExecStart=-/sbin/agetty --autologin root --noclear %I $TERM

  8. 退出根文件系统,卸载根文件系统。

打包根文件系统

  1. 制作空镜像,在此处指定你最终想要做的根文件系统镜像大小。dd if=/dev/zero of=ubuntu.ext4 bs=1M count=大小
  2. 将空镜像格式化为 ext4 格式,mkfs.ext4 ubuntu.ext4
  3. 挂载此镜像,将根文件系统的内容全部复制到镜像中。

    1
    2
    3
    mkdir mnt
    sudo mount ubuntu.ext4 ubuntu-base-24.04.1-base-arm64/
    sudo cp -rfp ubuntu-base-24.04.1-base-arm64/* mnt/
  4. 卸载此镜像 sudo umount mnt
  5. 使用 e2fsck 修复文件系统,因为我们是将一个小的文件系统塞入了一个大的镜像中,不修复存储可能会有问题,e2fsck -p -f ubuntu_rootfs.img
  6. 如果想要最小化文件系统,就输入resize2fs -M ubuntu.ext4,否则就什么也不用做了。

结语

最终,ubuntu.ext4 即为我们需要的根文件系统镜像。

本文参考了 构建Ubuntu20.04根文件系统并移植到RK3568,并有一些自己的想法,更多细节可以参考此文。