BusyBox init 与 systemd 怎么选
两条路的本质差异
BusyBox init 和 systemd 代表了 Linux init 系统的两种哲学:
| 维度 | BusyBox init | systemd |
|---|---|---|
| 代码量 | ~500 行 C | 数十万行 C + shell |
| 体积 | 含在 BusyBox 里,额外约 10KB | ~3MB 二进制 + 配套组件 |
| 依赖 | 无(静态编译 BusyBox 单文件) | dbus、udev、libsystemd、journald 等 |
| 配置方式 | /etc/inittab 简单文本 | unit 文件 + systemctl 命令 |
| 进程管理 | respawn 守护 | 完整的 unit 生命周期管理 |
| 并行启动 | 不支持(按 inittab 顺序) | 自动并行依赖无关的单元 |
| 日志 | syslogd 或无 | journald(二进制日志 + 索引) |
| 功能 | 够用即可 | 完整的进程管理框架 |
嵌入式设备为什么选 BusyBox init
体积约束是硬指标:一个典型路由器的根文件系统只有 4-8MB。BusyBox init 占 10KB,systemd 占 3MB——后者把可用空间吃掉了一半。IoT 设备(Flash 只有 2-4MB)根本放不下 systemd 的依赖链。
够用就好:嵌入式设备通常不需要 systemd 的以下特性:
- 复杂的依赖管理(After=、Requires=、Wants=)
- socket activation
- cgroup 资源隔离
- journald 二进制日志
- D-Bus 跨进程通信
- timer、path、socket 等多种 unit 类型
一个路由器真正需要 init 做的事情:
- 挂载 /proc /sys /dev
- 启动 syslogd 和 klogd
- 配置网络
- respawn 守护几个关键服务
- 提供串口 shell
- 响应 shutdown/reboot
这些 BusyBox init 全部能做,代码量只有几百行。
什么时候考虑 systemd
不是所有 Linux 系统都是嵌入式。以下场景 systemd 更合适:
- 桌面和笔记本:需要 logind(电源管理、会话管理)、udev(设备热插拔)、NetworkManager(网络管理)
- 服务器:需要复杂的服务依赖管理、并行启动、资源限制
- 需要现代特性:socket activation 让服务按需启动、timer unit 替代 cron、journald 的结构化日志查询
- 团队已有 systemd 经验:运维人员熟悉 systemctl 和 unit 文件
在这些场景用 BusyBox init 会很痛苦——手动配置每个守护进程、自己写日志滚动、没有依赖管理,维护成本反而比 systemd 高。
混合方案
一些轻量发行版尝试了中间路线:
| 方案 | 说明 | 体积 |
|---|---|---|
| Alpine Linux | OpenRC(不是 BusyBox init)+ musl + BusyBox | ~5MB 基础镜像 |
| Devuan | sysvinit + 现代包管理 | 较大 |
| Void Linux | runit(另一个极简 init)+ musl 可选 | 较小 |
| BusyBox 整套 | BusyBox init + BusyBox 全部工具 | ~1.1MB |
Alpine Linux 是容器领域最流行的轻量发行版,但它用的是 OpenRC 而不是 BusyBox init。OpenRC 是独立的 init 系统,比 BusyBox init 功能更强但也更大。
迁移建议
从 BusyBox init 到 systemd(设备升级或换发行版):
- 把 inittab 里每个 respawn 行转换成一个 service unit 文件
- rcS 里的初始化脚本拆分到 target 文件的 After= 依赖中
- respawn 换成 Restart=always + RestartSec=3
- 测试并行启动是否有隐式的顺序依赖
从 systemd 到 BusyBox init(新项目用嵌入式方案):
- 评估项目是否真的不需要 systemd 特性
- 如果只是"感觉应该用 BusyBox"但需要 socket activation 或依赖管理,可能还是选 OpenRC 或 runit
- BusyBox init 最适合从零开始、需求已知、体积约束明确的项目