Debootstrap 与 Yocto 实操教程

2026/06/01

Debootstrap 与 Yocto 实操教程

第一部分:Debootstrap

Debootstrap 是 Debian 官方提供的工具,用于构建 Debian/Ubuntu 根文件系统。相比 Buildroot 和 Yocto,Debootstrap 更简单直接,适合需要 Debian 生态的应用场景。

核心特点

使用场景

环境准备

docker run -it --name debootstrap-build \
  -v $(pwd)/workspace:/workspace \
  debian:bullseye bash

安装必要工具:

apt-get update && apt-get install -y \
  debootstrap \
  qemu-user-static \
  binfmt-support \
  wget \
  curl \
  sudo \
  locales

# 设置 locale
sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen
locale-gen
export LANG=en_US.UTF-8

基本用法

支持的架构:amd64 (x86_64)、arm64 (AArch64)、armel/armhf (ARM)、i386、ppc64el、riscv64

Debian 版本代号:stable (当前: Bookworm 12)、testing (Trixie)、unstable (Sid),或直接使用代号 bookworm, trixie, sid

构建 Debian Bookworm ARM64 RootFS:

mkdir -p /workspace/debian-rootfs
cd /workspace

# 最小安装
debootstrap --arch arm64 bookworm ./debian-rootfs http://deb.debian.org/debian

# 或包含推荐包
debootstrap --arch arm64 --include=locales,curl,wget,git,openssh-server \
  bookworm ./debian-rootfs http://deb.debian.org/debian

构建 Ubuntu RootFS:

mkdir -p /workspace/ubuntu-rootfs
cd /workspace

# Ubuntu 22.04 ARM64
debootstrap --arch arm64 jammy ./ubuntu-rootfs http://archive.ubuntu.com/ubuntu/

# Ubuntu 24.04 ARM64
debootstrap --arch arm64 noble ./ubuntu-rootfs http://archive.ubuntu.com/ubuntu/

跨架构构建(重要)

在 x86 机器上构建 ARM64 rootfs,需要 QEMU 模拟。

# 复制 QEMU 静态二进制到 rootfs
cp /usr/bin/qemu-aarch64-static ./debian-rootfs/usr/bin/

# 启用 binfmt_misc(容器内通常已启用)
mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc

配置 APT 源(可选优化):

# 进入 chroot 环境
LANG=C.UTF-8 chroot ./debian-rootfs /bin/bash

# 配置 APT
cat > /etc/apt/sources.list << 'EOF'
deb http://deb.debian.org/debian bookworm main contrib non-free
deb http://deb.debian.org/debian bookworm-updates main contrib non-free
deb http://deb.debian.org/debian-security bookworm-security main
EOF

# 更新包列表
apt-get update

# 安装必要组件
apt-get install -y \
  locales \
  sudo \
  dbus \
  udev \
  systemd \
  network-manager

# 设置 locale
sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen
locale-gen
echo 'LANG=en_US.UTF-8' > /etc/default/locale

# 退出 chroot
exit

RootFS 基础配置

# 1. 设置主机名
echo "my-device" > ./debian-rootfs/etc/hostname

# 2. 配置网络
cat > ./debian-rootfs/etc/resolv.conf << 'EOF'
nameserver 8.8.8.8
nameserver 8.8.4.4
EOF

# 3. 设置 root 密码
chroot ./debian-rootfs /bin/bash -c "echo 'root:password' | chpasswd"
# 或清空密码(不安全,仅测试用)
chroot ./debian-rootfs /bin/bash -c "passwd -d root"

# 4. 添加用户
chroot ./debian-rootfs /bin/bash -c "useradd -m -s /bin/bash user"
chroot ./debian-rootfs /bin/bash -c "echo 'user:password' | chpasswd"
chroot ./debian-rootfs /bin/bash -c "echo 'user ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers"

# 5. 配置 SSH(可选)
chroot ./debian-rootfs /bin/bash -c "apt-get install -y openssh-server"
# 允许 root 登录(仅测试)
sed -i 's/#PermitRootLogin.*/PermitRootLogin yes/' ./debian-rootfs/etc/ssh/sshd_config

打包 RootFS

# 1. 创建 tarball
cd ./debian-rootfs
tar --numeric-owner -cvpzf ../debian-bookworm-arm64.tar.gz .
ls -lh ../debian-bookworm-arm64.tar.gz

# 2. 创建镜像文件
dd if=/dev/zero of=debian.img bs=1M count=2048 status=progress
mkfs.ext4 -F debian.img
mkdir -p /mnt/rootfs
mount -o loop debian.img /mnt/rootfs
tar -xzf debian-bookworm-arm64.tar.gz -C /mnt/rootfs
umount /mnt/rootfs

# 3. 使用 guestfish 自动化
apt-get install libguestfs-tools
guestfish --ro \
  --add debian.img \
  --mount /dev/sda1:/ \
  --download /etc/apt/sources.list /tmp/sources.list
guestfish \
  --add debian.img \
  --mount /dev/sda1:/ \
  --tar-in debian-bookworm-arm64.tar.gz /

测试 RootFS

使用 QEMU 启动:

# 需要内核镜像(从 debootstrap 外部获取)
wget https://boot.netboot.xyz/ipxe/nokernel/linux-aarch64 -O linux-aarch64

# 启动(需要目标板内核,这里用通用内核演示概念)
qemu-system-aarch64 \
  -M virt \
  -cpu cortex-a53 \
  -m 512M \
  -kernel vmlinuz \
  -initrd initrd.img \
  -append "root=/dev/vda console=ttyAMA0" \
  -drive file=debian.img,if=vda,format=raw \
  -nographic

使用 systemd-nspawn:

apt-get install systemd-container

# 进入 rootfs
systemd-nspawn -D ./debian-rootfs -M my-container

# 或后台运行
systemd-nspawn -bD ./debian-rootfs

使用 chroot:

# 挂载虚拟文件系统
mount -t proc proc ./debian-rootfs/proc
mount -t sysfs sys ./debian-rootfs/sys
mount --bind /dev ./debian-rootfs/dev

# 进入
chroot ./debian-rootfs /bin/bash

# ... 操作完成后
exit
umount ./debian-rootfs/dev
umount ./debian-rootfs/sys
umount ./debian-rootfs/proc

进阶配置

添加 ROS(如果需要):

chroot ./debian-rootfs /bin/bash

apt-get install -y curl
curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | apt-key add -
sh -c 'echo "deb http://packages.ros.org/ros/ubuntu bookworm main" > /etc/apt/sources.list.d/ros.list'

apt-get update
apt-get install -y ros-noetic-ros-base

exit

添加 Docker 支持:

chroot ./debian-rootfs /bin/bash

curl -fsSL https://get.docker.com | sh

# 或手动安装
apt-get install -y docker.io containerd
systemctl enable docker

exit

自定义 systemd 服务:

cat > ./debian-rootfs/etc/systemd/system/hello.service << 'EOF'
[Unit]
Description=Hello Service
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/hello.sh
Restart=always

[Install]
WantedBy=multi-user.target
EOF

cat > ./debian-rootfs/usr/bin/hello.sh << 'EOF'
#!/bin/bash
echo "Hello from rootfs!" | logger
while true; do
    sleep 60
done
EOF

chmod +x ./debian-rootfs/usr/bin/hello.sh
chroot ./debian-rootfs /bin/bash -c "systemctl enable hello"

Multistrap(高级用法)

当需要更精细控制时,使用 multistrap:

apt-get install multistrap

cat > multistrap.conf << 'EOF'
[General]
cleanup=true
noauth=true
unpack=true
debootstrap=minimal

[Minimal]
packages=locales,openssh-server,iputils-ping,curl,wget
source=http://deb.debian.org/debian
suite=bookworm
architectures=arm64

[Development]
packages=gcc,make,git,python3,cmake
source=http://deb.debian.org/debian
suite=bookworm
architectures=arm64
EOF

multistrap -f multistrap.conf -d ./rootfs

常见问题

Q: debootstrap 失败 “Releases file missing”

# 使用正确的 sources.list
debootstrap --foreign --no-check-gpg ...

# 或使用快照源
debootstrap bookworm ./rootfs http://snapshot.debian.org/archive/debian/20240101/

Q: 容器内无法运行 QEMU

# 检查 binfmt_misc
cat /proc/sys/fs/binfmt_misc/status

# 手动注册
echo ':aarch64:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\xb7:/usr/bin/qemu-aarch64-static:OC' > /proc/sys/fs/binfmt_misc/register

Q: 如何减小 rootfs 体积

# 清理 apt 缓存
chroot ./debian-rootfs /bin/bash -c "apt-get clean && rm -rf /var/lib/apt/lists/*"

# 清理日志
rm -rf ./debian-rootfs/var/log/*.log

# 清理临时文件
rm -rf ./debian-rootfs/tmp/*

# 重新打包
tar --numeric-owner -cvzf small-rootfs.tar.gz -C ./debian-rootfs .

参考链接:


第二部分:Yocto/OpenEmbedded

Yocto Project 是 Linux 基金会旗下的开源项目,提供了完整的嵌入式 Linux 构建框架。OpenEmbedded 是其核心构建引擎,Poky 是参考发行版。

架构

Yocto 架构
┌─────────────────────────────────────────────────────────────┐
│                        BitBake                               │
│                    (任务调度器)                                │
├─────────────────────────────────────────────────────────────┤
│  Meta-Layers (层层叠加的配置)                                  │
│  ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐           │
│  │ meta-poky│ │ meta-oe │ │ meta-yocto-bsp │ │ meta-custom │ │
│  └─────────┘ └─────────┘ └─────────┘ └─────────┘           │
├─────────────────────────────────────────────────────────────┤
│                    OpenEmbedded Core                          │
│                    (基础构建系统)                              │
└─────────────────────────────────────────────────────────────┘

关键术语

术语说明
Layer功能模块集合,一个 layer 就是一个目录
Recipe (.bb)软件包构建配方,描述如何获取、编译、打包
Recipe append (.bbappend)追加修改已有 recipe
BitBake任务调度器,类似 make 但更强大
conf配置文件目录
BSPBoard Support Package,板级支持包
SDKSoftware Development Kit,交叉编译工具链

环境准备

docker run -it --name yocto-build \
  -v $(pwd)/workspace:/yocto-build \
  debian:bullseye bash

安装依赖:

apt-get update && apt-get install -y \
  build-essential \
  git \
  wget \
  curl \
  cpio \
  unzip \
  rsync \
  bc \
  python3 \
  python3-dev \
  libncurses-dev \
  libncurses5-dev \
  libssl-dev \
  zlib1g-dev \
  bison \
  flex \
  patch \
  diffutils \
  file \
  gawk \
  locales \
  chrpath \
  sudo \
  which

# 设置 locale
sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen
locale-gen
export LANG=en_US.UTF-8

获取 Poky(Yocto 官方参考发行版)

# 方法一:Git 克隆(推荐)
cd /yocto-build
git clone -b scarthgap --depth 1 https://git.yoctoproject.org/poky
cd poky

# 方法二:下载 tarball
cd /yocto-build
wget http://downloads.yoctoproject.org/releases/yocto/yocto-5.0/poky-scarthgap-5.0.tar.bz2
tar xjf poky-scarthgap-5.0.tar.bz2
cd poky-scarthgap-5.0

构建流程

# 1. 初始化构建环境(必须使用 poky 中的脚本),会创建 build/ 目录并切入
source oe-init-build-env

查看可用机器:ls conf/machine/

常用机器:qemuarm64、qemux86-64、raspberrypi3-64、imx8mmevk

配置 conf/local.conf:

# 设置目标架构
MACHINE ??= "qemuarm64"

# 设置并行编译
PARALLEL_MAKE = "-j 8"
BB_NUMBER_THREADS = "8"

# 设置下载目录(加速重复构建)
DL_DIR ?= "/yocto-build/downloads"

# 设置构建产物输出目录
SSTATE_DIR ?= "/yocto-build/sstate-cache"

# 禁用不需要的组件加速构建
EXTRA_IMAGE_FEATURES = ""

构建镜像:

# 构建最小系统
bitbake core-image-minimal

# 构建带调试工具的镜像
bitbake core-image-minimal-dev

# 构建完整系统
bitbake core-image-full-cmdline

# 构建带 Qt5 的镜像(需要添加 meta-qt5 层)
bitbake core-image-qt

首次构建耗时 1-3 小时(网络和机器性能决定)。

关键配置文件

conf/local.conf:

# 机器选择
MACHINE ??= "qemuarm64"

# 打包格式
IMAGE_FSTYPES = "ext4 wic"

# 目标地域
IMAGE_LINGUAS = "en-us"

# 额外包
CORE_IMAGE_EXTRA_INSTALL = "packagegroup-core-ssh-openssh"

conf/bblayers.conf:

# 添加额外的 meta 层
BBLAYERS += " \
  /path/to/meta-qt5 \
  /path/to/meta-ros \
"

层管理

# 查看已有层
bitbake-layers show-layers

# 添加官方扩展层
git clone -b scarthgap https://github.com/ros/meta-ros.git
git clone -b scarthgap https://github.com/meta-qt5/meta-qt5.git
bitbake-layers add-layer /path/to/meta-ros
bitbake-layers add-layer /path/to/meta-qt5

# 创建自定义层
bitbake-layers create-layer meta-custom
# 结构:
# meta-custom/
# ├── conf/layer.conf
# ├── recipes-example/
# └── classes/

构建产物

ls tmp/deploy/images/qemuarm64/

产物包括:

QEMU 运行

# 方式一:使用 runqemu
runqemu qemuarm64 nographic

# 方式二:指定镜像
runqemu qemuarm64 tmp/deploy/images/qemuarm64/core-image-minimal-qemuarm64.ext4

# 带启动参数
runqemu qemuarm64 nographic bootparams="root=/dev/vda console=ttyAMA0,115200"

# 带端口映射(SSH 到 localhost:2222)
runqemu qemuarm64 user-net

进阶:创建自定义 Recipe

创建 meta-custom/recipes-hello/hello/hello_1.0.bb:

SUMMARY = "Hello World Application"
DESCRIPTION = "A simple hello world application"
HOMEPAGE = "https://example.com"
AUTHOR = "Your Name <[email protected]>"
SECTION = "apps"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"

SRC_URI = "file://hello.c \
           file://Makefile"

S = "${WORKDIR}"

do_compile() {
    oe_runmake
}

do_install() {
    install -d ${D}${bindir}
    install -m 0755 hello ${D}${bindir}
}

创建源码目录并编译:

mkdir -p meta-custom/recipes-hello/hello/files
# 放入 hello.c 和 Makefile
bitbake hello

常见问题

Q: 构建太慢怎么办

# 使用本地 sstate 缓存
SSTATE_DIR = "/yocto-build/sstate-cache"

# 使用可信上游
BB_NO_NETWORK = "0"

# 清理重建
bitbake core-image-minimal -c cleansstate
bitbake core-image-minimal

Q: 如何添加包到镜像

# 方法一:在 local.conf 中全局添加
IMAGE_INSTALL_append = " vim git"

# 方法二:创建 custom-image.bb
bitbake custom-image

Q: 如何修改已有包

使用 .bbappend:

# meta-custom/recipes-core/busybox/busybox_%.bbappend
FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
SRC_URI += "file://defconfig"

Yocto vs Buildroot 选择

维度Yocto/OpenEmbeddedBuildroot
学习曲线陡峭平缓
构建速度慢(首次)快
定制粒度源码级别包级别
生态大厂都在用社区驱动
适用场景商业产品、车规、工规快速原型、小批量

参考链接: