一、服务管理概述
OpenHarmony 的服务管理核心由 init 进程 负责。init 进程在系统启动时,通过解析特定格式的服务进程配置文件(.cfg
文件),来管理系统服务的启动、生命周期和权限控制。这种设计允许根据不同的业务场景灵活配置服务行为。
文档中提到的增值服务功能包括:
- 启动控制:控制服务在哪个阶段启动。
- 按需启动:服务在真正被需要时才拉起,节省系统资源。
- 命令执行:在服务生命周期的特定节点(如启动、停止、重启时)执行自定义命令。
- 定时启动:在指定时间后拉起服务。
- fd代持:init 进程可以为服务预先创建并管理文件描述符。
- 沙盒:为服务提供隔离的运行环境。
二、服务配置文件详解
服务配置文件是管理服务的核心,通常命名为 服务名.cfg
(例如 appspawn.cfg
),并遵循 JSON 格式。
1. 配置文件的位置与加载
配置文件通常放置在 /system/etc/init/
或 /vendor/etc/init/
目录下。init 进程在启动时会扫描并解析这些目录下的所有 .cfg
文件。
2. 核心配置字段说明
配置文件主要包含 services
和 jobs
等 JSON 对象。下表详细说明了 services
字段下各关键配置项的含义和用法:
字段名 | 是否必选 | 说明与示例 | 适用系统 |
---|---|---|---|
name |
必选 | 服务名称,需唯一且非空,长度≤32字节。例:"name": "myservice" |
小型、标准 |
path |
必选 | 执行文件路径和参数。第一个元素必须是路径。例:"path": ["/system/bin/myservice", "--arg1"] |
小型、标准 |
uid , gid |
必选 | 进程运行的用户ID和组ID。例:"uid": 1000 , "gid": 1000 |
小型、标准 |
once |
可选 | 是否为一次性进程。0 :常驻(退出后自动重启);1 :一次性(退出后不重启)。例:"once": 0 |
小型、标准 |
importance |
可选 | 标准系统 :进程优先级(-20到19,值越小优先级越高)。小型系统 :标记重要性(非0:重要进程,退出会触发系统重启)。例:"importance": -5 |
小型、标准 |
start-mode |
可选 | 服务的启动模式。boot :在 "init" 阶段启动;normal :在 "post-init" 阶段启动(默认);condition :按条件启动。例:"start-mode": "boot" |
标准系统 |
ondemand |
可选 | 是否按需启动。设为 true 后,init 不会主动启动该服务,而是在特定条件满足时(如 socket 有请求)才拉起。例:"ondemand": true |
小型、标准 |
critical |
可选 | 服务抑制机制。配置为数组 [M, N, T] ,其中 M=使能标志(1/0),N=时间段T秒内最大重启次数,T=时间窗口(秒)。超过限制则会重启系统。例:"critical": [1, 5, 60] |
小型、标准 |
secon |
可选 | 设置服务的 SELinux 安全上下文(标签)。需要在 SELinux 策略中预先定义。例:"secon": "u:r:my_service:s0" |
标准系统 |
3. 生命周期命令执行 (jobs
)
服务可以在其生命周期的不同阶段执行特定的命令序列(jobs)。
json
"services": [{
"name": "my_service",
"path": ["/system/bin/my_service"],
"jobs": {
"on-start": "services:my_service_start", // 服务进程fork后执行
"on-stop": "services:my_service_stop", // 服务停止时执行
"on-restart": "services:my_service_restart" // 服务重启时执行
}
}]
这些 jobs
需要在配置文件的 "jobs"
部分具体定义。
三、服务管理实用教程
1. 如何新增一个系统服务
以下是为系统新增一个名为 my_daemon
的常驻系统服务的标准流程:
a. 创建配置文件 (my_daemon.cfg
)
将配置文件放在代码仓的合适位置,例如 vendor/your_company/your_product/init_configs/
或 base/startup/init/services/etc/
。
json
// my_daemon.cfg
{
"jobs": [{
"name": "init",
"cmds": [
"start my_daemon" // 在init阶段启动该服务
]
}],
"services": [{
"name": "my_daemon",
"path": ["/system/bin/my_daemon", "--config=/data/my_daemon.conf"],
"uid": 1000,
"gid": 1000,
"once": 0,
"importance": 0,
"ondemand": false,
"sandbox": 1
}]
}
b. 修改编译脚本
确保你的服务可执行文件和配置文件能被编译系统打包到镜像中。通常需要在对应的 bundle.json
和 BUILD.gn
文件中添加构建目标。
c. 验证服务
- 编译并烧写系统镜像。
- 使用
ps
命令查看服务进程是否已启动:ps -ef | grep my_daemon
。 - 测试服务韧性:使用
kill
命令终止该进程,观察 init 进程是否会将其重新拉起(因为"once": 0
)。
2. 服务权限配置(DAC)
服务的 uid
和 gid
需要在系统的用户和组数据库中定义。
- 添加新用户/组 :如果服务使用了新的
uid
/gid
,需要在init
模块的/etc/passwd
和/etc/group
文件中添加相应条目。 - 高权限进程白名单 :如果服务的
uid
或gid
是root
或system
,必须在产品目录下的security_config/high_privilege_process_list.json
文件中将其加入白名单。
3. 服务权限配置(SELinux)
如果系统开启了 SELinux(通常处于 Enforcing 强制模式或 Permissive 宽容模式),需要为服务配置安全策略。
- 临时设置为宽容模式 (用于调试):在 shell 中执行
setenforce 0
。此时违反策略只会记录日志而不会阻止操作。 - 为服务定义标签 :
- 在
file_contexts
文件中定义可执行文件的标签:/system/bin/my_daemon u:object_r:my_daemon_exec:s0
- 在
type.te
等策略文件中定义标签的作用域和转换规则。
- 在
- 编写策略规则 (
.te
文件):允许你的服务域(如my_daemon
)访问其所需的资源(文件、端口等)。
4. 服务控制命令
OpenHarmony 提供了 begetctl
命令工具来手动管理服务。
-
启动/停止/重启服务 :
bashbegetctl start my_daemon begetctl stop my_daemon begetctl restart my_daemon
-
定时启动服务 :
begetctl timer_start my_daemon 5000
(5秒后启动)。
系统 API 也提供了相应的控制接口,如 ServiceControl
, StartServiceByTimer
等,但这些通常是给系统组件使用,需要相应的 DAC 和 SELinux 权限。
四、最佳实践与故障排查
- 最小权限原则 :为服务配置尽可能小的
uid
/gid
和caps
(能力集),并使用沙盒功能("sandbox": 1
)。 - 按需启动 :对于不总是需要运行的服务,设置
"ondemand": true
以提升系统启动速度和减少资源占用。 - 利用抑制机制 :为关键服务配置
critical
参数,防止其异常崩溃时无限重启拖垮系统。 - 调试 :
- 如果服务未能正常启动,首先使用
dmesg
或hilog
查看系统日志,寻找 init 进程报出的错误码(见文档中的错误码说明表)。 - 当怀疑是 SELinux 问题导致服务启动失败时,先将 SELinux 设置为 Permissive 模式(
setenforce 0
)进行测试。如果问题消失,则基本可以确定是 SELinux 策略需要调整。
- 如果服务未能正常启动,首先使用
关注鸿蒙百川带你学习更多鸿蒙操作系统知识