13. 构建基础根文件系统

借助SDK我们可以方便的一键构建Debian/Ubuntu镜像,构建基础文件系统的SDK脚本路径为:ebf-image-builder/scripts/debootstrap.sh

以下将讲解该脚本是如何构建文件系统的。

debootstrap.sh脚本使用了debootstrap工具来下载和安装所需的软件包,并创建一个基本的文件系统。

实现步骤操作如下:

1、设置必要的变量:

  • deb_arch:指定系统架构(如x86_64、armhf等)

  • deb_include:指定要包含的软件包列表

  • deb_exclude:指定要排除的软件包列表

  • deb_components:指定要包含的组件列表

  • deb_variant:指定使用的debootstrap变体(可选)

  • deb_distribution:指定发行版(debian或ubuntu)

  • deb_codename:指定发行版代号(如bionic、focal等)

  • tempdir:指定临时目录用于存储文件系统

2、设置APT代理(可选):

  • apt_proxy:指定APT代理(如果有)

3、设置镜像源:

  • deb_mirror:指定镜像源地址(默认为官方源)

4、运行debootstrap命令:

sudo debootstrap –no-merged-usr ${options} ${suite} “${target}” ${mirror}

此命令将在${target}目录中创建一个基本的Ubuntu文件系统,使用${mirror}指定的镜像源进行下载。

5、输出文件系统大小报告:

脚本会通过执行report_size函数来报告${target}目录的大小。

debootstrap.sh脚本内容如下:

ebf-image-builder/scripts/debootstrap.sh
  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
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
    DIR=$PWD

    . "${DIR}/.project"

    check_defines () {
          #http://linux.die.net/man/8/debootstrap

          unset options
          if [ ! "${deb_arch}" ] ; then
                echo "scripts/deboostrap_first_stage.sh: Error: deb_arch undefined"
                exit 1
          else
                options="--arch=${deb_arch}"
          fi

          if [ "${deb_include}" ] ; then
                include=$(echo ${deb_include} | sed 's/ /,/g' | sed 's/\t/,/g')
                #board_include=$(echo ${board_deb_include} | sed 's/ /,/g' | sed 's/\t/,/g')
                options="${options} --include=${include},${board_include}"
          fi

          if [ "${deb_exclude}" ] ; then
                exclude=$(echo ${deb_exclude} | sed 's/ /,/g' | sed 's/\t/,/g')
                options="${options} --exclude=${exclude}"
          fi

          if [ "${deb_components}" ] ; then
                components=$(echo ${deb_components} | sed 's/ /,/g' | sed 's/\t/,/g')
                options="${options} --components=${components}"
          fi

          #http://linux.die.net/man/8/debootstrap
          if [ "${deb_variant}" ] ; then
                #--variant=minbase|buildd|fakechroot|scratchbox
                options="${options} --variant=${deb_variant}"
          fi

          if [ ! "${deb_distribution}" ] ; then
                echo "scripts/deboostrap_first_stage.sh: Error: deb_distribution undefined"
                exit 1
          fi

          unset suite
          if [ ! "${deb_codename}" ] ; then
                echo "scripts/deboostrap_first_stage.sh: Error: deb_codename undefined"
                exit 1
          else
                suite="${deb_codename}"
          fi

          case "${deb_distribution}" in
          debian)
                if [ ! -f /usr/share/debootstrap/scripts/${suite} ] ; then
                      sudo ln -s /usr/share/debootstrap/scripts/sid /usr/share/debootstrap/scripts/${suite}
                fi
                if [ ! -f /usr/share/keyrings/debian-archive-keyring.gpg ] ; then
                      options="${options} --no-check-gpg"
                fi
                ;;
          ubuntu)
                if [ ! -f /usr/share/debootstrap/scripts/${suite} ] ; then
                      sudo ln -s /usr/share/debootstrap/scripts/gutsy /usr/share/debootstrap/scripts/${suite}
                fi
                if [ ! -f /usr/share/keyrings/ubuntu-archive-keyring.gpg ] ; then
                      options="${options} --no-check-gpg"
                fi
                ;;
          esac
          options="${options} --foreign"

          unset target
          if [ ! "${tempdir}" ] ; then
                echo "scripts/deboostrap_first_stage.sh: Error: tempdir undefined"
                exit 1
          else
                target="${tempdir}"
          fi

          unset mirror
          if [ ! "${apt_proxy}" ] ; then
                apt_proxy=""
          fi
          if [ ! "${deb_mirror}" ] ; then
                case "${deb_distribution}" in
                debian)
                      deb_mirror="deb.debian.org/debian"
                      ;;
                ubuntu)
                      deb_mirror="ports.ubuntu.com/"
                      ;;
                esac
          fi
          mirror="http://${apt_proxy}${deb_mirror}"
    }

    report_size () {
          echo "Log: Size of: [${tempdir}]: $(du -sh ${tempdir} 2>/dev/null | awk '{print $1}')"
    }

    check_defines

    echo "Log: Creating: [${deb_distribution}] [${deb_codename}] image for: [${deb_arch}]"

    if [ "${apt_proxy}" ] ; then
          echo "Log: using apt proxy: [${apt_proxy}]"
    fi

    echo "Log: Running: debootstrap in [${tempdir}]"
    ###FIXME: --no-merged-usr eventually we will support, but as of 1.0.101+ it's back, so default to pre...
    echo "Log: [sudo debootstrap --no-merged-usr ${options} ${suite} ${target} ${mirror}]"
    sudo debootstrap --no-merged-usr ${options} ${suite} "${target}" ${mirror}
    report_size
    #
  • 第9到14行,deb_arch指定系统架构,deb_arch定义在ebf-image-builder/configs/boards/ebf_stm_mp157_star.conf

1
deb_arch="armhf"
  • 第16到20行,deb_include指定要包含的软件包列表,deb_include定义在ebf-image-builder/configs/common.conf

1
2
3
4
5
6
deb_include="apt-transport-https ca-certificates connman curl dosfstools\
                gnupg gnupg2 ifupdown initramfs-tools isc-dhcp-client nano \
                net-tools netcat rsync sudo udhcpd parted mtd-utils mmc-utils\
                rng-tools haveged wpasupplicant udhcpc openssh-server avahi-daemon\
                gpiod kpartx jq libgpiod-dev rfkill usbutils exfat-fuse exfat-utils \
                ssh alsa-utils"
  • 第22到25行,deb_exclude指定要排除的软件包列表,deb_exclude定义在ebf-image-builder/configs/common.conf

1
2
deb_exclude="aptitude aptitude-common groff-base info install-info man-db manpages\
                              manpages-dev tasksel tasksel-data"
  • 第27到30行,deb_components指定要包含的组件列表,deb_components定义在ebf-image-builder/configs/common.conf

1
deb_components="main universe multiverse"
  • 第33到36行,deb_variant指定使用的debootstrap变体(可选),SDK中没有定义deb_variant

  • 第38到40行,deb_distribution指定发行版(debian或ubuntu),定义在ebf-image-builder/configs/common.conf

1
2
3
4
5
#debian
deb_distribution="lubancat"

#ubuntu
deb_distribution="ubuntu"
  • 第44到49行,deb_codename指定发行版代号(如bionic、focal等),定义在ebf-image-builder/configs/common.conf

1
2
3
4
5
6
7
8
deb_codename=$DISTRIB_RELEASE
    ...
    if [[ $DISTRIB_RELEASE == bionic ]]; then
    ...
    release="18.04"
    ...
    if [[ $DISTRIB_RELEASE == focal ]]; then
      release="20.04"
  • 第51到69行,根据${deb_distribution}是Debian还是ubuntu,脚本会检查是否存在${suite}版本的debootstrap脚本,也就是前面的deb_codename发行版本。如果不存在,则会创建一个符号链接,Debian指向Sid版本,Sid是Debian不稳定版,Ubuntu指向gutsy版本,Ubuntu 7.10,然后脚本会检查是否存在ubuntu-archive-keyring.gpg密钥文件,如果不存在,则会将–no-check-gpg选项添加到${options}中。最后,脚本会将–foreign选项添加到${options}中,指示debootstrap创建一个基本系统,而不是完整的系统。

  • 第71到77行,指定临时目录用于存储文件系统。

  • 第79到82行,apt_proxy指定APT代理,SDK没有指定。

  • 第83到93行,指定镜像源地址(默认为官方源)

  • 第96到98行,通过执行report_size函数来报告${target}目录的大小。

  • 第133行,运行debootstrap命令,将在${target}目录中创建一个基本的文件系统,使用${mirror}指定的镜像源进行下载。

以上,除了文件系统的发行版本,我们比较关心的是文件系统预安装了哪些软件包,定义在deb_include变量中,如果读者需要修改安装的软件包,修改common.conf文件中的deb_include变量即可。

可见,此构建文件系统的脚本十分依赖SDK中其他配置文件,建议完整构建系统镜像从而构建文件系统。