本手册以 GNU Make 为主构建方式;Make、交叉编译及用户态示例已在上述环境验证。Meson 为可选构建方式,使用前应确认当前源码树包含
meson.build。官方原始文档见README.md、BUILD、doc/getting_started.md、doc/linux/DINIT-AS-INIT.md与各 man 页面。
目录
1. 引言
Dinit 是一个现代、轻量且健壮的服务管理器,也可以在 Linux 上作为系统初始化程序(PID 1)运行。它主要解决以下问题:
- 按依赖关系并行启动服务;
- 监控前台进程,并在异常退出后按策略恢复;
- 在依赖失效时回退相关服务,依赖恢复后再重新启动;
- 通过简洁的文本文件描述服务;
- 同时支持系统实例和普通用户实例。
Dinit 的设计目标是简洁、可移植、易于理解,并与设备管理、日志、网络、登录等现有组件协作,而不是把所有系统功能都纳入自身。
1.1 阅读对象
本手册面向具备 Linux 基础知识的开发、系统集成和运维人员。阅读前建议了解:
- 进程、信号、前台/后台守护进程;
- Linux 文件系统和挂载;
- 用户、用户组及文件权限;
- 启动加载器、内核命令行与 initramfs 的基本作用。
1.2 使用方式选择
| 场景 | 运行身份 | 服务目录 | 风险 |
|---|---|---|---|
| 用户态服务管理 | 普通用户 | ~/.config/dinit.d |
低,适合学习和应用进程托管 |
| 系统服务管理 | root,但非 PID 1 | /etc/dinit.d |
中 |
| 系统 Init | PID 1 | /etc/dinit.d |
高,需准备恢复手段 |
2. 环境与前置条件
2.1 硬件 / 目标平台
| 项目 | 说明 |
|---|---|
| 目标架构 | AArch64(ARM 64-bit),对应 mr536 板卡(全志 Sunxi 系列) |
| 内核版本 | 工具链二进制要求 Linux ≥ 5.15(见 file 输出 for GNU/Linux 5.15.0) |
| 运行模式 | 可作为系统 init(PID 1),亦可作为普通用户态服务管理器 |
Dinit 本身是纯 C++ 用户态程序,不依赖特殊硬件外设。作为 init 使用时建议内核已启用
devtmpfs、cgroups v2。
2.2 编译机(宿主机)软件依赖
在 WSL(Ubuntu 22.04)中已验证可用。构建前请确保已安装:
bash
# 宿主机原生编译器(用于生成 mconfig-gen 辅助工具,交叉编译必需)
sudo apt install -y build-essential g++ make
# 文档构建(可选,仅生成 man 页面)
sudo apt install -y m4
# Meson 构建方式所需(可选)
sudo apt install -y meson ninja-build
# 可选:能力(capabilities)支持库。本手册的交叉编译默认禁用,
# 若需启用请额外安装并交叉编译 libcap。
# sudo apt install -y libcap-dev
验证宿主机工具链:
bash
$ g++ --version # 宿主机 g++(Ubuntu 11.4.0 实测可用)
$ make --version # GNU Make 4.3 实测可用
2.3 目标板(交叉)工具链
本手册使用 mr536 提供的 OpenWrt GCC 交叉工具链:
bash
# 请将下面的路径替换为你本地的项目路径
$ ls /path/to/mr536/
toolchain-sunxi-glibc-gcc-1320 # 工具链根目录
$ ls /path/to/mr536/toolchain-sunxi-glibc-gcc-1320/bin/ | grep g++
aarch64-openwrt-linux-gnu-g++ # ← 本手册使用的 C++ 交叉编译器
$ /path/to/mr536/toolchain-sunxi-glibc-gcc-1320/bin/aarch64-openwrt-linux-gnu-g++ --version
aarch64-openwrt-linux-gnu-g++.bin (OpenWrt GCC 13.2.0 r16734+1-70dacd5d5f) 13.2.0
工具链关键路径:
| 路径 | 用途 |
|---|---|
.../bin/aarch64-openwrt-linux-gnu-g++ |
C++ 交叉编译器 |
.../aarch64-openwrt-linux-gnu/sysroot/ |
目标板 sysroot(glibc + 头文件) |
注意(OpenWrt 工具链特性) :编译时会出现
warning: environment variable 'STAGING_DIR' not defined。该告警无害。如需消除,可设置:
bashexport STAGING_DIR=/path/to/mr536/toolchain-sunxi-glibc-gcc-1320/aarch64-openwrt-linux-gnu
3. 获取、构建与安装
3.1 获取源码
建议使用固定版本标签或经过验证的提交,避免生产构建随主分支变化:
bash
git clone https://github.com/davmac314/dinit.git
cd dinit
git checkout <经过验证的版本或提交>
如源码由 Windows 检出后再进入 WSL,需注意 CRLF 行尾问题。
3.2 Make 构建(主要且推荐)
Dinit 官方主构建流程依赖 GNU Make 和支持 C++11 的编译器。官方说明 GCC 4.9+ 或 Clang 约 5.0+ 可用;工程环境建议使用仍受维护的较新编译器。
在官方直接支持的平台上,可直接运行 make 采用默认配置。需要修改安装路径、编译器或功能开关时,运行 ./configure 生成 mconfig;某些源码版本也可通过 make mconfig 生成或准备配置。
原生构建(WSL)
bash
cd /path/to/dinit
./configure --platform=Linux
make -j"$(nproc)"
# 产物:src/dinit src/dinitctl src/dinit-check src/dinit-monitor
构建产物位于 src/:
| 产物 | 用途 |
|---|---|
dinit |
服务管理守护进程,可作为 PID 1 |
dinitctl |
服务控制客户端 |
dinit-check |
服务描述检查工具 |
dinit-monitor |
服务状态监控工具 |
shutdown |
系统关机工具,主要供 Dinit 作为 PID 1 时使用 |
关键 mconfig / 配置变量
| 变量 | 作用 |
|---|---|
CXX |
目标平台 C++ 编译器 |
CXX_FOR_BUILD |
构建机编译器,交叉编译时用于宿主辅助工具 |
CXXOPTS / CXXFLAGS |
C++ 编译选项,具体名称以当前版本配置文件为准 |
LDFLAGS |
链接选项 |
SBINDIR |
系统管理程序安装目录 |
MANDIR |
man 页面安装目录 |
SYSCONTROLSOCKET |
系统实例默认控制 socket |
3.3 Meson 构建(可选/实验性)
仅当源码树包含 meson.build 时使用:
bash
meson setup builddir
meson compile -C builddir
# 启用单元测试等选项时,以当前源码的 meson_options.txt 为准
meson setup builddir -Dunit-tests=true
meson test -C builddir
sudo meson install -C builddir
查看当前版本支持的选项:
bash
meson configure builddir
Meson 选项可能随版本变化。正式交付建议优先使用项目
BUILD文档明确支持的 Make 流程。
3.4 交叉编译(mr536 工具链,AArch64)
关键点:必须区分目标编译器 CXX 与宿主编译器 CXX_FOR_BUILD。目标 sysroot 缺少可选库时,应显式关闭相关能力。
bash
cd /path/to/dinit
TC=/path/to/mr536/toolchain-sunxi-glibc-gcc-1320
export PATH="$TC/bin:$PATH"
export STAGING_DIR="$TC/aarch64-openwrt-linux-gnu"
rm -f mconfig
./configure \
CXX=aarch64-openwrt-linux-gnu-g++ \
CXX_FOR_BUILD=g++ \
--platform=Linux \
--disable-capabilities \
--disable-ioprio \
--disable-oom-adj
make -j"$(nproc)"
验证产物:
bash
file src/dinit
readelf -l src/dinit | grep interpreter
除架构外,还应确认动态链接器路径及目标板所需共享库均存在。
3.5 安装与打包
bash
# 安装到当前系统
sudo make install
# 安装到临时根目录/目标 rootfs
make DESTDIR=/path/to/rootfs install
# Meson
sudo meson install -C builddir
DESTDIR=/path/to/rootfs meson install -C builddir
DESTDIR 只改变本次安装根目录,适合制作固件或软件包,不应误写为目标设备的运行时路径。
3.6 构建测试
bash
make check
make check-igr
交叉产物不能直接在 x86_64 宿主机运行;应在目标板或对应仿真环境执行运行测试。
4. 快速上手:用户态服务管理
以下流程不修改系统 Init,适合首次学习和验证。
4.1 创建用户服务目录与 boot
Dinit 用户态默认从 $HOME/.config/dinit.d 读取服务描述,并自动启动名为 boot 的服务。
bash
# 1) 准备服务目录与 boot 服务(internal 类型,不启动外部进程)
mkdir -p ~/.config/dinit.d/boot.d
cat > ~/.config/dinit.d/boot <<'EOF'
type = internal
waits-for.d: boot.d
EOF
# 2) 后台启动 dinit(-q 静默,-u 用户态实例,-p 指定控制 socket)
src/dinit -q -u -p /tmp/dinit.sock &
sleep 1
# 3) 查看服务列表(此时仅有 boot)
src/dinitctl -u -p /tmp/dinit.sock list
# 期望输出: [[+] ] boot
4.2 添加并管理一个 process 服务
bash
# 写一个长期运行的 process 服务(以 sleep 模拟守护进程)
cat > ~/.config/dinit.d/sleeper <<'EOF'
type = process
command = /bin/sleep 600
restart = true
EOF
DCTL="src/dinitctl -u -p /tmp/dinit.sock"
$DCTL start sleeper # 启动并标记为 active
$DCTL list # 看到 sleeper 及其 pid
$DCTL status sleeper # 查看状态:State=STARTED, 含 Process ID
$DCTL stop sleeper # 停止服务
4.3 启用默认启动
enable 会在 boot 服务的 waits-for.d 目录中创建持久依赖:
bash
$DCTL enable sleeper
$DCTL disable sleeper
也可直接从命令行启动指定服务,但生产配置应使用 boot 和依赖目录统一管理。
4.4 验证崩溃自动重启
bash
$DCTL start sleeper
OLD_PID=$($DCTL status sleeper | awk '/Process ID/{print $3}')
kill "$OLD_PID"
sleep 1
$DCTL status sleeper
若新 PID 与 OLD_PID 不同,说明服务被重新拉起。测试结束:
bash
$DCTL stop sleeper
$DCTL shutdown # 关闭用户态 dinit 实例
实测输出(WSL 验证通过):
[2] list
[[+] ] boot
[3] start sleeper -> Service 'sleeper' started.
[[+] ] boot
[[+] ] sleeper (pid: 28550)
[4] status sleeper
State: STARTED
Activation: explicitly started
Process ID: 28550
[5] stop sleeper -> Service 'sleeper' stopped.
[6] shutdown -> Shutting down dinit... / Connection closed.
5. 服务配置与日常使用
5.1 构建与配置补充参考
Dinit 使用 shell 脚本 configure + Makefile 的轻量构建系统(非 autotools/cmake):
configure ──► mconfig # 生成顶层构建配置(编译器/路径/特性开关)
Makefile ──► build/ + src/ # build/ 生成 mconfig-gen 工具与 mconfig.h
# src/ 编译各 .cc → dinit / dinitctl / ...
构建目标产物(src/ 下):
| 产物 | 说明 |
|---|---|
dinit |
核心守护进程(可作 init) |
dinitctl |
服务控制客户端(start/stop/list/status...) |
dinit-check |
服务描述文件语法/依赖检查器 |
dinit-monitor |
服务状态变更监听工具 |
shutdown |
关机/重启工具(仅 Linux,随 dinit 一并安装到 sbin,并创建 halt/reboot/poweroff/soft-reboot 软链) |
5.1.1 配置选项(./configure)
常用选项(完整列表见 ./configure --help):
| 选项 | 默认(Linux) | 说明 |
|---|---|---|
--prefix=PREFIX |
/usr |
安装主前缀 |
--bindir / --sbindir / --mandir |
PREFIX/bin / PREFIX/sbin / PREFIX/share/man |
各类文件目录 |
--syscontrolsocket=PATH |
/run/dinitctl |
系统控制 socket 路径 |
--enable/disable-shutdown |
Linux 下 enable | 是否构建 shutdown 系列工具 |
--enable/disable-cgroups |
enable | cgroups 支持 |
--enable/disable-capabilities |
auto(有 libcap 则启用) | Linux capabilities 支持(需 libcap) |
--enable/disable-ioprio |
auto | I/O 优先级(需 linux/ioprio.h) |
--enable/disable-oom-adj |
enable | OOM score 调整 |
--enable/disable-strip |
enable | 安装时 strip 调试信息 |
构建变量(可作 VAR=value 参数传入):
CXX:C++ 编译器CXX_FOR_BUILD:宿主机 编译器(交叉编译时必需,用于编译mconfig-gen等辅助工具)CXXFLAGS/CXXFLAGS_EXTRA:编译选项LDFLAGS/LDFLAGS_EXTRA:链接选项--platform=PLATFORM:手动指定平台(交叉编译时建议显式给出,如Linux)
5.1.2 交叉编译参考(mr536 工具链,AArch64)
关键点:交叉编译必须同时指定 目标 CXX 与 宿主机 CXX_FOR_BUILD(后者用于编译运行于构建机的辅助工具)。目标板通常无 libcap/ioprio/oom 相关头文件,建议在交叉编译时禁用这些可选特性。
bash
cd /path/to/dinit
# 配置(推荐写成脚本以免 PATH 引号问题)
cat > /tmp/build-mr536.sh <<'SH'
#!/bin/bash
set -e
cd /path/to/dinit
TC=/path/to/mr536/toolchain-sunxi-glibc-gcc-1320
export PATH="$TC/bin:$PATH" # 让 configure 能找到交叉 g++
export STAGING_DIR="$TC/aarch64-openwrt-linux-gnu" # 消除 OpenWrt 的 STAGING_DIR 告警(可选)
rm -f mconfig
./configure \
CXX=aarch64-openwrt-linux-gnu-g++ \
CXX_FOR_BUILD=g++ \
--platform=Linux \
--disable-capabilities \
--disable-ioprio \
--disable-oom-adj
make -j"$(nproc)"
SH
bash /tmp/build-mr536.sh
验证产物架构:
bash
$ file src/dinit
src/dinit: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV),
dynamically linked, interpreter /lib/ld-linux-aarch64.so.1,
for GNU/Linux 5.15.0, not stripped
构建说明:
- 交叉编译时 configure 会自动禁用
-fno-rtti(规避部分平台编译器与异常处理的 bug),属正常行为。-flto、-fsanitize(仅测试用)等会在 configure 阶段自动探测是否可用。- 生成的
mconfig为顶层配置,make时会据此生成build/includes/mconfig.h。
5.1.3 安装参考
bash
# 安装到目标板根文件系统(DESTDIR 方式,常用于嵌入式打包)
make DESTDIR=/path/to/rootfs install
# 产物落点:
# $DESTDIR/usr/bin/{dinit,dinitctl,dinit-check,dinit-monitor}
# $DESTDIR/sbin/{shutdown,halt,reboot,soft-reboot,poweroff}
# $DESTDIR/usr/share/man/man{5,8}/...
5.1.4 测试参考(需原生环境)
bash
make check # 单元测试(src/tests)
make check-igr # 集成测试(src/igr-tests)
交叉编译产物的测试需在目标板上执行;宿主机上
make check使用的是原生编译产物。
5.2 服务配置
5.2.1 服务描述文件
Dinit 通过服务描述文件发现服务。每个文件即一个服务,文件名=服务名。
| 角色 | 默认搜索目录 |
|---|---|
| 系统实例(root) | /etc/dinit.d,其次 /usr/local/lib/dinit.d、/lib/dinit.d |
| 用户实例 | $HOME/.config/dinit.d |
服务按需懒加载(首次 start/被依赖时才读取描述文件)。
服务类型(type)
| 类型 | 说明 |
|---|---|
process |
前台常驻进程,dinit 直接持有并监控其 pid(首选) |
bgprocess |
会自行 fork 到后台(如传统 daemon),通过 pid-file 追踪 |
scripted |
由脚本启动/停止(执行到完成即视为 started) |
internal |
无外部进程,常用于分组/检查点(如 boot、loginready) |
triggered |
需外部触发事件才能启动 |
重要原则 :把守护进程跑成前台模式 注册为
process,dinit 才能监控它。例如 sshd 用/usr/sbin/sshd -D、smbd 用-F(foreground)。
常用配置项
ini
type = process # 服务类型
command = /usr/sbin/sshd -D # 启动命令(前台运行!)
stop-command = ... # 停止命令(可选)
run-as = nobody # 以指定用户运行
restart = true # 崩溃后自动重启
logfile = /var/log/foo.log # 日志文件(该路径必须在该服务启动前可写!)
pid-file = /run/foo.pid # bgprocess 的 pid 文件
# 依赖关系(见 5.2.2)
depends-on: <svc> # 硬依赖:被依赖服务必须先启动成功
depends-ms: <svc> # 机器启动依赖:类似 depends-on 但不强制运行时同步
waits-for: <svc> # 等待:等它启动完再启动本服务,但不要求它成功
after: <svc> # 仅排序,无依赖语义(尽量少用)
# 选项(options:)
options: starts-log # 此服务就绪后开始把 dinit 缓冲日志落盘
完整选项见 man 页 dinit-service(5)。
5.2.2 依赖关系(核心概念)
Dinit 的精髓在于依赖。启动一个服务会先 拉起其依赖;停止一个无人依赖的服务会级联停止其依赖。
boot ──depends-on──► loginready ──depends-on──► syslogd
└──► dbusd
└──waits-for.d: boot.d/ ──► (各开机自启服务)
依赖关键字选择建议:
- 关键依赖用
depends-on::被依赖失败时本服务也不启动,能让 boot 失败被正确感知 → 触发恢复流程。 waits-for:仅做时序等待,不阻断启动;用于非关键前置。- 尽量避免
after:/before:(无依赖语义、不会级联停止)。
5.2.3 默认启动(boot 与 waits-for.d)
boot 是 dinit 默认拉起的服务。典型写法:
ini
# /etc/dinit.d/boot
type = internal
waits-for.d: boot.d # boot.d/ 中每个软链指向一个开机自启服务
通过 dinitctl enable/disable <svc> 自动在 boot.d/ 创建/删除软链,实现开机自启管理(等价于 systemd 的 enable)。
5.2.4 process 示例:sshd
ini
# /etc/dinit.d/sshd
type = process
command = /usr/sbin/sshd -D
restart = true
waits-for: syslogd
depends-on: loginready
更多系统级服务模板见 doc/linux/services/(含 boot、udevd、filesystems、rcboot、syslogd、ttyN、recovery、single 等)。
5.2.5 scripted 示例:一次性初始化
ini
# /etc/dinit.d/app-prepare
type = scripted
command = /usr/local/libexec/app-prepare start
stop-command = /usr/local/libexec/app-prepare stop
depends-on: root-rw
start-timeout = 30
stop-timeout = 10
scripted 服务的启动命令成功退出后,服务才进入 started 状态。脚本必须正确返回退出码,并保证重复执行安全。
5.2.6 配置校验与热加载
部署前务必用 dinit-check 检查服务描述语法与依赖错误:
bash
dinit-check /etc/dinit.d/sshd # 检查单个文件
dinit-check -d /etc/dinit.d # 检查整个目录
dinitctl reload sshd # 重新读取简单配置改动
dinitctl restart sshd # 需要时重启以使配置生效
6. 高级部署:作为系统 Init
!WARNING
Dinit 作为 PID 1 时,服务文件、挂载或登录配置错误可能导致设备无法启动或无法登录。必须先备份 rootfs、保留串口控制台或救援系统,并在测试环境验证。
6.1 前提准备
- 可修改内核命令行的引导加载程序,例如 GRUB 或 U-Boot;
- 可用的 initramfs/initrd 或等效早期启动逻辑;
- initramfs 能挂载
/proc、/sys、/dev、/run,并最终执行根文件系统中的/sbin/init; - 设备节点管理器(如 eudev)、
getty/login、shell、日志服务及网络工具; - 串口、救援分区、可回滚 A/B 分区或其他恢复通道。
6.2 最小系统服务集合
实际名称可调整,但通常至少需要:
| 服务 | 类型建议 | 作用 |
|---|---|---|
boot |
internal |
系统默认启动目标 |
early-filesystems |
scripted |
准备 /proc、/sys、/dev、/run |
root-rw / filesystems |
scripted |
fsck、根分区读写及其他挂载 |
udevd |
process |
设备事件与节点管理 |
syslogd |
process |
系统日志 |
network |
scripted 或 process |
网络初始化 |
loginready |
internal |
登录服务前置检查点 |
tty1 / serial-getty |
process |
本地或串口登录 |
recovery |
scripted 或 process |
启动失败后的恢复入口 |
getty 示例:
ini
# /etc/dinit.d/tty1
type = process
command = /sbin/agetty --noclear tty1 linux
restart = true
depends-on: loginready
options: runs-on-console
串口设备名、波特率和终端类型必须按目标板修改。
6.3 部署步骤
部署步骤:
- 交叉编译并安装到 rootfs(见第 3 章)。
- 准备服务描述 :将
doc/linux/services/模板按板子实际情况修改后放入$ROOTFS/etc/dinit.d/。 - initramfs 预挂载 (推荐由 initramfs 完成):
/proc、/sys、/dev(devtmpfs)、/run(tmpfs)。其中/run可写是 dinit 能立即创建控制 socket 的前提。 - 离线检查配置 :对目标 rootfs 中的服务目录执行
dinit-check。 - 低风险测试 :不替换原
/sbin/init,通过一次性内核参数init=/sbin/dinit启动。 - 验收:确认文件系统、设备节点、网络、日志、登录、关机和重启均正常。
- 正式启用 :验证通过后,再让
/sbin/init指向已安装的 Dinit。
bash
ln -sfn /usr/bin/dinit "$ROOTFS/sbin/init"
执行前必须确认实际安装路径;某些配置会把 dinit 安装到 /sbin/dinit。
启动流程(由服务实现):
挂载早期虚拟文件系统 → 启动 udevd → 设硬件时钟 → fsck 根文件系统
→ 根文件系统重挂为 rw → 清理 /tmp、/var/run,配 lo,设主机名
→ 启动 syslogd → 启动其他 daemon(网络/ssh...)→ loginready → getty 登录
6.4 测试与回滚清单
- 启动前记录原始
/sbin/init指向; - 不删除原 Init 二进制及其配置;
- 保存一条可从引导菜单恢复原
init=参数的启动项; - 验证
boot失败时能进入 recovery shell; - 验证串口或本地
getty可登录; - 验证
dinitctl shutdown、重启及断电流程; - 验证看门狗、挂载、网络和核心业务服务;
- 正式切换后首次启动安排现场或远程恢复人员值守。
7. 故障排查
7.1 运行时控制速查(dinitctl)
bash
dinitctl list # 列出所有已加载服务及状态
dinitctl status <svc> # 单个服务详情(含 pid)
dinitctl start <svc> # 启动并标记 active
dinitctl stop <svc> # 停止(会停止其独占的依赖)
dinitctl release <svc> # 取消 active 标记,无依赖则停止(更"软"的 stop)
dinitctl enable <svc> # 开机自启(在 boot.d 建软链)
dinitctl disable <svc> # 取消开机自启
dinitctl start --pin <svc> # 固定为启动态(禁止被 stop/级联停止)
dinitctl unpin <svc> # 解除固定
dinitctl shutdown # 关闭 dinit(停止所有服务)
状态图例:
| 显示 | 含义 |
|---|---|
[[+] ] |
已启动 + 显式 active |
[{+} ] |
已启动,但仅因被依赖而运行(非显式 active) |
[ {-}] |
已停止 |
<< / >> |
正在启动 / 正在停止 |
用户态/系统实例选择:root 默认连系统实例;普通用户默认连用户实例。-s 强制系统实例、-u 强制用户实例,-p PATH 指定控制 socket。
7.2 常见问题
A. ./configure 报 bad interpreter: /bin/sh^M
源码含 Windows CRLF 行尾。执行 dos2unix configure configs/mconfig.Linux.sh Makefile src/Makefile build/Makefile build/tools/Makefile。
B. CXX is not a working C++ compiler / command not found
交叉编译时未把工具链加入 PATH,或未用脚本统一 export PATH(命令行直接传含空格/括号的 PATH 易出错)。确保 export PATH=/opt/toolchain/mr536/toolchain-sunxi-glibc-gcc-1320/bin:$PATH 且同时 指定 CXX_FOR_BUILD=g++。
C. STAGING_DIR not defined 告警
OpenWrt 工具链 wrapper 的无害告警。消除:export STAGING_DIR=/opt/toolchain/mr536/toolchain-sunxi-glibc-gcc-1320/aarch64-openwrt-linux-gnu。
D. 交叉编译链接报 cannot find -lcap / 找不到 capabilities 头文件
目标 sysroot 缺 libcap。若目标板不需要 capabilities,构建时加 --disable-capabilities(本手册默认即如此)。
E. 服务启动失败:logfile 不可写
logfile 指定的目录在该服务启动时刻必须可写。根文件系统在 rootrw(重挂 rw)之前是只读的 → 早期服务应把日志放 /run,或用 log-type = buffered 缓存在内存。
F. 服务偶发启动失败 / 时序问题
通常是漏声明依赖 (并行启动下偶发竞态)。为关键服务补 depends-on:(文件系统可写、伪文件系统挂载、系统时间、syslog)。不要依赖启动顺序"碰运气"。
G. 控制台服务死锁/卡住
runs-on-console 同时只能有一个服务占用控制台。仅需显示输出用 shares-console;确需独占输入再用 runs-on-console。
H. 调试启动问题
- 用 shell 脚本代替
/sbin/init,在其中exec dinit并传任意参数。 - 临时在某 tty 放一个
command = /sbin/agetty tty6 linux-c -n -l /bin/bash、去掉依赖、设term-signal = none与stop-timeout = 0,保留一个常驻调试 shell。 - 用
dinit-check预检服务描述。
I. WSL 下运行报 socket/权限问题
WSL 中建议用户态测试用 -u -p /tmp/dinit.sock 显式指定 socket 路径,避免与系统 socket 冲突。
7.3 日志与监控
- 服务输出默认可由
logfile落盘;未指定时早期可log-type = buffered缓存。 dinit-monitor <svc> -- <cmd>可在服务状态变化时执行命令(接告警/通知)。- 系统启动日志由
syslogd承接(需starts-log选项触发 dinit 把缓冲日志刷出)。
8. 附录
8.1 dinitctl 命令速查
| 命令 | 作用 |
|---|---|
start <svc> |
启动并显式激活服务 |
stop <svc> |
停止并取消显式激活 |
restart <svc> |
重启服务 |
wake <svc> |
启动但不显式激活 |
release <svc> |
取消显式激活,无活动依赖者时自动停止 |
status <svc> |
查看服务状态、PID 和失败原因 |
list |
列出已加载服务 |
enable <svc> |
持久加入默认启动依赖 |
disable <svc> |
删除对应的默认启动依赖 |
reload <svc> |
重新加载允许在线变更的描述项 |
catlog <svc> |
查看 buffer 类型日志 |
signal <sig> <svc> |
向服务进程发送信号 |
shutdown |
停止全部服务;系统实例会进入系统关机流程 |
disable只移除指定的持久waits-for依赖;若其他服务依赖该服务,它仍可能被启动。
8.2 关键路径速查表
| 用途 | 路径 / 命令 |
|---|---|
| 交叉编译器 | /opt/toolchain/mr536/toolchain-sunxi-glibc-gcc-1320/bin/aarch64-openwrt-linux-gnu-g++ |
| sysroot | /opt/toolchain/mr536/toolchain-sunxi-glibc-gcc-1320/aarch64-openwrt-linux-gnu/sysroot |
| 系统服务目录 | /etc/dinit.d |
| 用户服务目录 | ~/.config/dinit.d |
| 系统控制 socket | /run/dinitctl(可经 --syscontrolsocket 改) |
| 构建配置 | 顶层 mconfig(由 ./configure 生成) |
| 服务模板参考 | doc/linux/services/ |
| 官方文档 | README.md、doc/getting_started.md、doc/linux/DINIT-AS-INIT.md、man 页 |
8.3 官方参考
本手册中 Make 交叉编译与用户态快速启动流程已在 WSL Ubuntu 22.04 + mr536 工具链环境下实测;系统 Init 切换必须在具体目标板上另行完成恢复演练与验收。