强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

BusyBox 搭建 mini rootfs 完全指南 / 第 12 章:最佳实践

第 12 章:最佳实践

12.1 安全加固

12.1.1 最小权限原则

# 1. 不以 root 运行应用
# /etc/passwd
appuser:x:1000:1000:Application User:/home/appuser:/bin/sh

# 2. 使用 su-exec 或 gosu 切换用户
$ su-exec appuser /usr/bin/myapp

# 3. 设置文件权限
$ chmod 700 /usr/local/bin/myapp
$ chown appuser:appuser /usr/local/bin/myapp

# 4. 移除不需要的 Applet
# 编译时禁用危险工具
# make menuconfig → 禁用:
#   - su (不需要时)
#   - mount (不需要时)
#   - reboot/halt/poweroff
#   - telnetd

12.1.2 文件系统安全

# 1. 只读 rootfs
# /etc/fstab
/dev/mmcblk0p2  /       ext4    ro,noatime   0  1
tmpfs           /tmp    tmpfs   defaults     0  0
tmpfs           /var    tmpfs   defaults     0  0

# 2. 使用 squashfs(压缩只读)
$ mksquashfs rootfs rootfs.sqsh -comp xz

# 3. 使用 read-only overlay
mount -t overlay overlay \
    -o lowerdir=/ro-rootfs,upperdir=/tmp/overlay,workdir=/tmp/work \
    /mnt/rootfs

# 4. 禁用不需要的挂载点
# 从 inittab 中移除不需要的挂载

12.1.3 网络安全

# 1. 使用 iptables 限制访问
# 允许 SSH
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# 允许已建立连接
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# 拒绝其他
iptables -A INPUT -j DROP

# 2. 使用 dropbear 替代 telnet
# Dropbear 是轻量级 SSH 服务器
$ dropbear -R -w -s  # 禁止 root 登录

# 3. 禁用不需要的网络服务
# 从 inittab 中移除:
# - telnetd(不安全)
# - ftpd(不安全)

12.1.4 用户管理

# 1. 设置强密码
$ passwd root
$ echo 'root:$6$rounds=100000$salt$hash' > /etc/shadow

# 2. 禁用不必要的账户
$ sed -i 's/^nobody:.*/nobody:!:0:0:99999:7:::/' /etc/shadow

# 3. 使用 /etc/securetty 限制登录终端
# /etc/securetty
console
ttyS0

# 4. 禁用空密码
$ sed -i 's/root::/root:*:/' /etc/shadow

12.1.5 安全加固清单

项目操作优先级
禁用不需要的 Appletmenuconfig
只读 rootfsfstab/mount
非 root 运行应用su-exec
SSH 替代 Telnetdropbear
防火墙规则iptables
禁用空密码shadow
移除调试工具menuconfig
定期更新 BusyBox源码更新

12.2 体积优化

12.2.1 BusyBox 编译优化

# 1. 只启用需要的 Applet
$ make menuconfig
# 禁用所有不需要的功能

# 2. 静态编译 + musl(更小)
$ make CC=musl-gcc

# 3. 优化级别
# Settings → (-Os) Additional CFLAGS
# -Os = 体积优化
# -Oz = 最大体积优化(GCC 8+)

# 4. Strip 符号表
$ strip busybox

# 5. UPX 压缩(可选)
$ sudo apt install upx
$ upx --best busybox

12.2.2 体积对比

配置x86_64 大小
默认配置 (glibc, 动态)~2.1MB
默认配置 (glibc, 静态)~2.8MB
默认配置 (musl, 静态)~960KB
默认配置 (musl, 静态, strip)~847KB
默认配置 (musl, 静态, strip, -Os)~780KB
最小 Applet 集 (musl)~200KB
全部 Applet (musl)~3.5MB
UPX 压缩后~400KB

12.2.3 rootfs 体积优化

# 1. 使用 squashfs 压缩
$ mksquashfs rootfs rootfs.sqsh -comp xz -b 256K
# 典型压缩比: 3-5x

# 2. 移除不需要的文件
$ rm -rf rootfs/usr/share/doc
$ rm -rf rootfs/usr/share/man
$ rm -rf rootfs/usr/share/info

# 3. 使用 musl 替代 glibc
# musl libc 约 600KB,glibc 约 2MB

# 4. 合并符号链接目录
# 将 /bin, /sbin, /usr/bin, /usr/sbin 合并
$ ln -s bin rootfs/usr/bin
$ ln -s bin rootfs/usr/sbin
$ ln -s bin rootfs/sbin

12.2.4 内核体积优化

# 使用最小内核配置
$ make tinyconfig
# 然后只启用需要的功能

# 压缩内核
# 支持的压缩算法:
# gzip  - 压缩率一般,速度快
# bzip2 - 压缩率好
# lzma  - 压缩率好,速度慢
# xz    - 压缩率最好
# lzo   - 压缩率一般,速度最快
# lz4   - 压缩率一般,速度极快

12.3 嵌入式应用

12.3.1 典型嵌入式架构

┌─────────────────────────────────────────┐
│              用户应用                     │
│   (Web UI, MQTT, 数据采集等)             │
├─────────────────────────────────────────┤
│              运行时环境                   │
│   (libcurl, OpenSSL, SQLite 等)          │
├─────────────────────────────────────────┤
│              BusyBox                     │
│   (Shell, 系统工具, init)                │
├─────────────────────────────────────────┤
│              Linux 内核                   │
│   (设备驱动, 文件系统, 网络栈)            │
├─────────────────────────────────────────┤
│              硬件平台                    │
│   (ARM SoC, Flash, RAM, 外设)            │
└─────────────────────────────────────────┘

12.3.2 系统启动脚本

#!/bin/sh
# /etc/init.d/rcS - 嵌入式系统启动脚本

# 挂载文件系统
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t tmpfs -o size=16M tmpfs /tmp
mount -t devtmpfs devtmpfs /dev

# 设备初始化
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s

# 设置网络
ifconfig lo 127.0.0.1 up
udhcpc -i eth0 -b -q

# 启动看门狗(如果存在)
[ -c /dev/watchdog ] && watchdog -t 30 /dev/watchdog &

# 启动应用
/usr/bin/myapp &

echo "System ready."

12.3.3 看门狗集成

# /etc/init.d/watchdog
#!/bin/sh

DAEMON="/usr/bin/myapp"
WATCHDOG_DEV="/dev/watchdog"
HEALTH_FILE="/tmp/health"

# 启动看门狗
start_watchdog() {
    if [ -c "$WATCHDOG_DEV" ]; then
        watchdog -t 60 "$WATCHDOG_DEV"
    fi
}

# 喂狗
feed_watchdog() {
    if [ -c "$WATCHDOG_DEV" ]; then
        echo -n 'V' > "$WATCHDOG_DEV"
    fi
}

# 健康检查
check_health() {
    if [ -f "$HEALTH_FILE" ]; then
        return 0
    fi
    return 1
}

# 主循环
start_watchdog
while true; do
    if check_health; then
        feed_watchdog
    else
        echo "Health check failed!"
    fi
    sleep 30
done

12.3.4 OTA 升级方案

#!/bin/sh
# /usr/bin/ota-update

UPDATE_URL="https://server/update/rootfs.sqsh"
UPDATE_FILE="/tmp/rootfs.sqsh"

# 下载更新
echo "Downloading update..."
wget -O "$UPDATE_FILE" "$UPDATE_URL"

# 校验
echo "Verifying..."
sha256sum -c /tmp/update.sha256 || exit 1

# 写入备用分区
echo "Installing..."
dd if="$UPDATE_FILE" of=/dev/mmcblk0p3 bs=4M

# 切换启动分区
echo "b" > /proc/sys/kernel/reboot_param

# 重启
reboot

12.3.5 电源管理

#!/bin/sh
# /usr/bin/power-manager

# 低功耗模式
low_power_mode() {
    echo 0 > /sys/class/leds/status/brightness
    echo mem > /sys/power/state
}

# 正常模式
normal_mode() {
    echo 1 > /sys/class/leds/status/brightness
}

# 优雅关机
graceful_shutdown() {
    echo "Shutting down..."
    sync
    umount -a
    poweroff
}

# 信号处理
trap 'graceful_shutdown' TERM
trap 'low_power_mode' USR1
trap 'normal_mode' USR2

12.4 调试技巧

12.4.1 系统调试

# 1. 开启内核调试
# 内核参数:
loglevel=7 initcall_debug

# 2. 使用 strace
$ strace -f -o trace.log /bin/myapp
$ strace -e trace=open,read,write /bin/myapp

# 3. 使用 ltrace(如果编译了)
$ ltrace /bin/myapp

# 4. 查看系统调用
$ cat /proc/[pid]/syscall

# 5. 查看打开的文件
$ ls -la /proc/[pid]/fd/

# 6. 查看内存映射
$ cat /proc/[pid]/maps

12.4.2 网络调试

# 1. 网络连通性
$ ping -c 3 8.8.8.8
$ traceroute 8.8.8.8

# 2. DNS 查询
$ nslookup example.com

# 3. 端口扫描
$ nc -zv 192.168.1.1 80

# 4. 网络统计
$ netstat -tlnp
$ cat /proc/net/tcp

# 5. ARP 表
$ arp -a

12.4.3 应用调试

# 1. 核心转储
$ ulimit -c unlimited
# 运行程序...
# core 文件生成后使用 gdb 分析

# 2. 日志记录
# /etc/init.d/rcS
exec > /var/log/rcS.log 2>&1
set -x  # 打印每条命令

# 3. 远程调试
# 使用 dropbear SSH
$ scp -r /tmp/debug user@remote:/tmp/

# 4. 内存分析
$ cat /proc/[pid]/status | grep -i vm
VmPeak:    12340 kB
VmSize:    12340 kB
VmRSS:      8192 kB

# 5. CPU 分析
$ top -p [pid]

12.4.4 常见问题排查

问题排查方法
Kernel panic检查 init 路径、rootfs、驱动
网络不通ifconfig、route、ping、DNS
启动慢bootchartd、dmesg、init 日志
内存不足/proc/meminfo、ps、OOM killer
磁盘满df、du、日志轮转
应用崩溃strace、核心转储、日志

12.5 性能优化

12.5.1 启动优化

# 1. 减少 init 脚本
# 只保留必要的 sysinit 操作

# 2. 使用 readahead
# 预读常用文件到内存

# 3. 延迟初始化
# 将非关键服务移到后台
/usr/bin/non-critical-service &

# 4. 内核参数优化
# 减少内核日志
echo 1 > /proc/sys/kernel/printk

# 5. 使用压缩内核
# lz4 压缩,启动时解压更快

12.5.2 运行时优化

# 1. 内存管理
echo 1 > /proc/sys/vm/drop_caches      # 清理缓存
echo 50 > /proc/sys/vm/swappiness      # 减少 swap 使用

# 2. I/O 调度
echo noop > /sys/block/mmcblk0/queue/scheduler  # Flash 设备

# 3. CPU 频率
echo performance > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor

# 4. 网络优化
echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse
echo 5 > /proc/sys/net/ipv4/tcp_fin_timeout

12.6 生产部署检查清单

12.6.1 发布前检查

检查项操作状态
静态编译file busybox 确认
strip 符号strip busybox
只读 rootfsfstab 配置
非 root 应用用户配置
防火墙规则iptables 配置
SSH 访问dropbear 配置
看门狗watchdog 脚本
日志配置syslogd 配置
时间同步ntpd 配置
OTA 升级测试升级流程

12.6.2 部署脚本

#!/bin/sh
# deploy.sh - 生产部署脚本

set -e

IMAGE="$1"
DEVICE="${2:-/dev/mmcblk0}"

if [ -z "$IMAGE" ]; then
    echo "Usage: $0 <image> [device]"
    exit 1
fi

echo "=== Production Deployment ==="
echo "Image: $IMAGE"
echo "Device: $DEVICE"
echo ""

# 1. 验证镜像
echo "[1/5] Verifying image..."
sha256sum -c "${IMAGE}.sha256"

# 2. 备份当前系统
echo "[2/5] Creating backup..."
dd if="${DEVICE}p2" of="/tmp/backup-$(date +%Y%m%d).img" bs=4M

# 3. 写入新镜像
echo "[3/5] Writing image..."
dd if="$IMAGE" of="${DEVICE}p2" bs=4M status=progress
sync

# 4. 验证写入
echo "[4/5] Verifying write..."
dd if="${DEVICE}p2" bs=4M count=$(stat -c%s "$IMAGE" | awk '{print int($1/4194304)+1}') | sha256sum

# 5. 完成
echo "[5/5] Deployment complete!"
echo "Please reboot to apply changes."

12.7 持续集成

12.7.1 自动化构建

# .github/workflows/build.yml
name: Build BusyBox

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    
    - name: Install dependencies
      run: |
        sudo apt-get update
        sudo apt-get install -y build-essential gcc make
    
    - name: Build BusyBox
      run: |
        make defconfig
        sed -i 's/# CONFIG_STATIC is not set/CONFIG_STATIC=y/' .config
        make -j$(nproc)
    
    - name: Test
      run: |
        ./busybox --list | wc -l
        ./busybox ls -la
    
    - name: Upload artifact
      uses: actions/upload-artifact@v3
      with:
        name: busybox
        path: busybox

12.8 总结与展望

12.8.1 本教程回顾

章节内容
1-3BusyBox 基础概念、编译和使用
4-5rootfs 构建和 Init 系统
6-9网络、Shell、工具和系统管理
10-11Buildroot 和 Docker 集成
12最佳实践和生产部署

12.8.2 进阶学习路径

初级 ──→ 中级 ──→ 高级
│         │         │
├─ BusyBox 基础    ├─ Buildroot 定制    ├─ 内核裁剪
├─ rootfs 构建     ├─ 驱动开发         ├─ Yocto 项目
├─ Shell 脚本      ├─ OTA 升级         ├─ 安全加固
└─ 基本调试        └─ 性能优化         └─ 商用部署

12.8.3 推荐资源

资源链接
BusyBox 官网https://busybox.net
Buildroot 手册https://buildroot.org
嵌入式 Linux 社区https://elinux.org
Bootlin 培训https://bootlin.com/training
Linux From Scratchhttps://linuxfromscratch.org

扩展阅读


上一章: 第 11 章 — Docker 中使用
返回: 目录