MTK平台开机脚本配置技巧,亲测有效不踩坑
在MTK平台开发中,配置开机自启动脚本看似简单,实则暗藏多个关键细节。很多开发者在调试过程中反复遇到“脚本没执行”“权限被拒绝”“SELinux报错”“属性未生效”等问题,往往耗费数小时甚至一两天才定位到真正原因。本文基于真实项目经验,梳理出一套经过多款MTK芯片(MT6765、MT6785、MT8788)验证的稳定配置流程,不讲理论套话,只说实操要点、避坑提示和可直接复用的代码片段。
1. 核心原则:先验证再集成,分步闭环验证
很多问题源于“一步到位”的错误思路——把脚本、te策略、init.rc修改一次性提交编译,结果开机失败却无法快速定位是哪一环出了问题。正确做法是分四步闭环验证,每步都确保有明确可观测的结果:
- 脚本能否手动执行成功(
adb shell下运行) - 脚本能否通过init服务方式执行(不依赖SELinux策略时临时关闭验证)
- SELinux策略是否加载且生效(
dmesg | grep avc无拒绝日志) - 开机后关键效果是否达成(如属性设置、文件生成、进程存在)
每一步都必须有可验证输出,例如设置一个test.boot.ok=1属性,或向/data/misc/test/boot.log写入时间戳。没有输出即等于没执行,这是排查的第一铁律。
2. 脚本编写:路径、权限与执行环境三重校验
2.1 脚本存放位置与路径声明
MTK平台推荐将开机脚本统一放在/system/bin/目录下(非/system/xbin/或/vendor/bin/),原因如下:
/system/bin/在init.rc中默认具有root:shell权限,无需额外修改file_contextsinit进程默认以root身份执行该路径下的二进制和脚本,兼容性最好- 避免因
/vendor/bin/挂载时机晚于init.rc解析导致脚本找不到
脚本示例(/system/bin/init.mtk.boot.sh):
#!/system/bin/sh # 注意:必须使用 /system/bin/sh,不可写成 /bin/sh 或 /system/xbin/sh # MTK平台的sh解释器路径固定,写错将静默失败 # 第一步:立即设置一个可检测的属性(最可靠的执行证据) setprop sys.mtk.boot.script 1 # 第二步:记录执行时间(用于确认是否真正在开机阶段运行) echo "[BOOT] $(date) - init.mtk.boot.sh executed" >> /data/misc/test/boot.log # 第三步:执行业务逻辑(示例:创建标志文件) touch /data/misc/test/boot_done.flag chmod 644 /data/misc/test/boot_done.flag # 第四步:可选——启动一个后台守护进程(需注意进程生命周期) # nohup /system/bin/my_daemon > /dev/null 2>&1 &2.2 关键避坑点
- Shebang行必须顶格,且路径绝对准确:
#!/system/bin/sh不能有多余空格,不能写成#!/system/bin/sh(末尾空格) - 脚本必须可执行:
chmod 755 /system/bin/init.mtk.boot.sh,否则init会跳过执行 - 避免使用
/data以外的临时路径:/tmp、/dev等在早期init阶段可能未挂载或不可写 - 禁止在脚本中调用
reboot、poweroff等危险命令:可能导致系统无法正常启动
3. SELinux策略配置:te文件与file_contexts精准匹配
MTK平台SELinux策略分散在device/mediatek/sepolicy/下,切勿修改platform目录,所有定制策略应放入basic/non_plat/子目录。
3.1 te策略文件(device/mediatek/sepolicy/basic/non_plat/test_boot.te)
# 定义服务域类型 type test_boot_service, domain; type test_boot_service_exec, exec_type, vendor_file_type, file_type; # 允许init以该域启动服务 init_daemon_domain(test_boot_service); # 允许该服务读取/执行自身文件 allow test_boot_service test_boot_service_exec:file { read open getattr execute }; # 允许该服务设置系统属性(关键!否则setprop失败) allow test_boot_service system_prop:property_service set; # 允许该服务写入/data/misc/目录(如需记录日志) allow test_boot_service data_file:dir { add_name remove_name }; allow test_boot_service data_file:file { create write getattr }; # 可选:如需访问网络或设备节点,按需添加 # allow test_boot_service net_admin:capability net_admin; # allow test_boot_service devpts:chr_file { read write };注意:
init_daemon_domain()已隐含domain_auto_trans()能力,无需额外声明auto_trans规则。
3.2 file_contexts映射(device/mediatek/sepolicy/basic/non_plat/file_contexts)
在该文件末尾添加一行(必须单独一行,前后无空格):
/system/bin/init\.mtk\.boot\.sh u:object_r:test_boot_service_exec:s0- 正则转义必须完整:
.需写为\.,否则匹配失败 - 路径必须与实际安装路径完全一致:若脚本放在
/vendor/bin/,此处必须改为/vendor/bin/init\.mtk\.boot\.sh - 标签名必须与te文件中定义的
test_boot_service_exec严格一致
4. init.rc服务定义:独立rc文件 + 显式seclabel
MTK平台强烈建议不修改system/core/rootdir/init.rc主文件,而是在device/mediatek/common/init/下新建专属rc文件(如init.mtk.boot.rc),并确保其被init自动加载。
4.1 创建device/mediatek/common/init/init.mtk.boot.rc
# MTK平台开机自启动服务 service mtk_boot_script /system/bin/init.mtk.boot.sh class main user root group root oneshot seclabel u:object_r:test_boot_service_exec:s0 # 可选:添加触发条件(确保在关键服务之后启动) on property:sys.boot_completed=1 start mtk_boot_script4.2 确保rc文件被加载
检查device/mediatek/common/init/init.common.rc中是否包含:
import /init.mtk.boot.rc若无,则添加。import语句必须位于on early-init或on init块之外,且在import /init.usb.rc等标准rc之后。
验证方法:编译后解包
ramdisk.img,确认init.mtk.boot.rc存在于根目录,且init.rc中存在对应import行。
5. 编译与验证全流程:从push到量产的五步法
5.1 快速验证(无需整包编译)
adb root && adb remountadb push init.mtk.boot.sh /system/bin/adb shell chmod 755 /system/bin/init.mtk.boot.shadb shell /system/bin/init.mtk.boot.sh→ 检查getprop sys.mtk.boot.script是否为1adb shell cat /data/misc/test/boot.log→ 确认时间戳存在
通过则脚本本身无问题。
5.2 SELinux临时关闭验证(定位策略问题)
adb shell setenforce 0 adb reboot # 开机后检查属性和日志 adb shell getprop sys.mtk.boot.script # 应为1 adb shell cat /data/misc/test/boot.log # 应有新时间戳若此时成功,说明问题100%在SELinux策略; 失败则回到脚本或rc配置检查。
5.3 SELinux策略调试(关键日志抓取)
adb shell dmesg | grep avc | tail -20 # 常见错误示例: # avc: denied { set } for property=sys.mtk.boot.script scontext=u:r:test_boot_service:s0 tcontext=u:object_r:system_prop:s0 tclass=property_service # 对应需添加:allow test_boot_service system_prop:property_service set;5.4 整包编译与烧录
- 修改
Android.mk或Android.bp,确保init.mtk.boot.rc被复制到ramdisk - 在
BoardConfig.mk中确认BOARD_SEPOLICY_DIRS += device/mediatek/sepolicy/basic/non_plat - 编译
make snod生成新system.img和ramdisk.img - 烧录后执行
adb shell getenforce确认为Enforcing
5.5 量产前必做检查清单
| 检查项 | 命令/方法 | 期望结果 |
|---|---|---|
| 脚本是否存在且可执行 | adb shell ls -l /system/bin/init.mtk.boot.sh | -rwxr-xr-x |
| rc文件是否加载 | adb shell cat /proc/1/cmdline | 包含init.mtk.boot.rc |
| SELinux策略是否加载 | adb shell sesearch -A | grep test_boot_service | 有输出规则 |
| 属性是否设置成功 | adb shell getprop sys.mtk.boot.script | 1 |
| 日志是否写入 | adb shell tail -5 /data/misc/test/boot.log | 有最新时间戳 |
6. 常见问题与根因分析(附解决方案)
6.1 “脚本完全没执行”,getprop始终为空
根因1:
init.rc中seclabel标签名与file_contexts不一致
解决:sesearch -A \| grep "test_boot_service_exec"确认标签加载成功根因2:
init.mtk.boot.rc未被import,或import语句位置错误
解决:解包ramdisk.img,检查init.rc内容及init.mtk.boot.rc是否存在根因3:脚本shebang路径错误(如写成
/bin/sh)
解决:adb shell file /system/bin/init.mtk.boot.sh确认解释器路径
6.2 “脚本执行了但setprop失败”
- 根因:SELinux缺少
property_service set权限
解决:在test_boot.te中添加allow test_boot_service system_prop:property_service set;
6.3 “日志写入失败,提示Permission denied”
- 根因:
/data/misc/test/目录不存在或权限不足
解决:在脚本开头添加mkdir -p /data/misc/test && chmod 755 /data/misc/test
6.4 “开机后进程存在,但属性被清空”
- 根因:
init在on property:sys.boot_completed=1后重置了部分属性
解决:改用persist.前缀属性(如setprop persist.sys.mtk.boot 1),该属性重启不丢失
7. 进阶技巧:让开机脚本更健壮、更可控
7.1 添加执行状态反馈机制
在脚本末尾加入:
# 记录执行状态码(0=成功,非0=失败) echo $? > /data/misc/test/boot_exit_code # 同时写入属性便于上层APP读取 setprop sys.mtk.boot.exit_code $?上层应用可通过SystemProperties.get("sys.mtk.boot.exit_code")实时获取结果。
7.2 支持动态开关(适配测试/量产模式)
在/data/misc/test/boot_config中预置配置:
# 内容示例: ENABLED=true LOG_LEVEL=DEBUG脚本中读取:
if [ "$(cat /data/misc/test/boot_config 2>/dev/null | grep ENABLED=true)" ]; then echo "[INFO] Boot script enabled" # 执行主逻辑 else echo "[INFO] Boot script disabled by config" exit 0 fi7.3 错误自动上报(仅限工程机)
if [ $? -ne 0 ]; then echo "[ERROR] Script failed at line $LINENO" >> /data/misc/test/boot_error.log # 触发上报服务(需预置) am startservice -n com.mtk.debug/.BootErrorService fi获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。