news 2026/9/24 6:08:50

手把手教你写Android开机启动shell脚本(附测试)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
手把手教你写Android开机启动shell脚本(附测试)

手把手教你写Android开机启动shell脚本(附测试)

1. 前言:为什么需要开机启动脚本?

在做Android系统级开发或定制时,经常会遇到这样一个需求:设备一开机,就自动执行某个任务。比如:

  • 自动开启某个后台服务
  • 设置系统属性用于后续流程判断
  • 挂载特殊分区或初始化硬件
  • 清理缓存、备份日志等维护操作

这些任务如果靠应用层去监听BOOT_COMPLETED广播来做,不仅延迟高,还可能因权限问题失败。而通过init 进程启动的 shell 脚本,可以在系统早期阶段运行,权限更高、时机更早。

本文将带你从零开始,完整实现一个 Android 开机启动 shell 脚本,并提供实际测试方法。内容基于 Android 8.0 环境验证通过,适用于大多数 AOSP 或 MTK/高通平台的定制系统开发。

你不需要是 SELinux 专家,也不用对 init.rc 了如指掌——只要跟着步骤走,就能成功跑通。


2. 实现原理简述

Android 的启动流程中,init进程是第一个用户空间进程(PID=1),它会解析/init.rc及其包含的.rc文件,根据配置启动各种服务和执行命令。

我们可以通过以下方式让一个 shell 脚本在开机时自动运行:

  1. 编写一个可执行的 shell 脚本
  2. 将脚本放入系统镜像的指定路径(如/system/bin/
  3. .rc文件中定义一个service来调用该脚本
  4. 配置 SELinux 策略允许该服务运行
  5. 编译刷机后验证效果

整个过程看似简单,但最容易卡住的地方就是SELinux 权限问题。别担心,我们会一步步解决。


3. 第一步:编写你的开机启动脚本

3.1 创建脚本文件

新建一个名为init.test.sh的文件,内容如下:

#!/system/bin/sh # 设置一个系统属性,用于验证脚本是否执行 setprop sys.boot.test 1 # 输出日志到 dmesg,方便调试 log -t "InitTest" -p i "开机启动脚本已执行" # 可选:创建一个标记文件(需注意目录权限) # touch /data/local/tmp/boot_script_ran

3.2 注意事项

  • 解释器路径必须正确:Android 系统通常使用/system/bin/sh,不是 Linux 常见的/bin/sh
  • 不要写错 shebang 行#!/system/bin/sh前不能有空格或 BOM
  • 避免操作敏感目录:测试阶段建议只设置属性或打日志,避免因文件权限导致失败
  • 脚本要可执行:确保编译进系统时权限为755

你可以先手动 push 到手机试试看能否运行:

adb push init.test.sh /data/local/tmp/ adb shell chmod 755 /data/local/tmp/init.test.sh adb shell /data/local/tmp/init.test.sh adb shell getprop sys.boot.test # 应该输出 1

如果这步都跑不通,说明脚本本身有问题,请先修复。


4. 第二步:为脚本添加 SELinux 策略

这是很多人踩坑最多的地方。即使关闭了 SELinux(enforcing=0),Android 仍然会检查类型标签(file_contexts)是否匹配,否则init不会启动服务。

4.1 新建 TE 策略文件

在你的设备目录下创建 SELinux 策略文件,例如 MTK 平台常见路径:

device/mediatek/sepolicy/basic/non_plat/test_service.te

内容如下:

# 定义服务类型 type test_service, coredomain; # 定义可执行文件类型 type test_service_exec, exec_type, file_type, vendor_file_type; # 允许 init 启动这个域的服务 init_daemon_domain(test_service) # 如果你想调试,可以临时设为宽容模式(不推荐长期使用) # permissive test_service;

4.2 添加 file_contexts 映射

编辑或创建:

device/mediatek/sepolicy/basic/non_plat/file_contexts

添加一行,告诉系统这个脚本文件应该属于什么安全上下文:

/(system\/vendor|vendor)/bin/init\.test\.sh u:object_r:test_service_exec:s0

注意:这里路径是/system/bin//vendor/bin/,取决于你把脚本放哪。正则表达式要用转义点号。

如果你把脚本放在/system/bin/init.test.sh,那最终打包时必须确保它在这个位置,并且上下文正确。


5. 第三步:在 .rc 文件中注册服务

不要直接修改/init.rc,而是找厂商提供的扩展.rc文件,比如:

  • init.mtk.rc
  • init.vendor.rc
  • 或者你自己加一个init.custom.rc

推荐做法是在init.${project}.rc中添加服务定义。

5.1 添加 service 定义

在合适的.rc文件中加入:

service test_service /system/bin/init.test.sh class main user root group root oneshot seclabel u:object_r:test_service_exec:s0
参数说明:
字段说明
class main属于主类服务,随 main class 启动
user/group root以 root 身份运行(谨慎使用)
oneshot只运行一次,适合脚本任务;如果不加,会不断重启
seclabel必须与 file_contexts 中定义的类型一致

5.2 替代方案:直接执行 command

如果你想更轻量,也可以不用 service,直接在.rc中写:

on property:sys.boot_completed=1 exec u:object_r:test_service_exec:s0 root root -- /system/bin/init.test.sh

这种方式更适合一次性命令,且能控制触发时机(比如等 boot_completed 再执行)。


6. 第四步:编译并刷入系统

6.1 放置脚本到源码目录

init.test.sh放入系统镜像中,例如:

system/bin/init.test.sh

并在Android.mkAndroid.bp中声明为可执行文件。

示例Android.mk

LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := init.test.sh LOCAL_SRC_FILES := init.test.sh LOCAL_MODULE_CLASS := EXECUTABLES LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES) LOCAL_MODULE_TAGS := optional LOCAL_STRIP_MODULE := false include $(BUILD_PREBUILT)

或者Android.bp

prebuilt_executable { name: "init.test.sh", srcs: ["init.test.sh"], owner: "your_company", relative_install_path: "bin", mode: "0755", }

6.2 编译系统镜像

mka systemimage -j$(nproc)

烧写后重启设备。


7. 第五步:如何测试脚本是否生效?

7.1 方法一:检查系统属性

最简单的验证方式:

adb shell getprop sys.boot.test

如果返回1,说明脚本成功执行了。

7.2 方法二:查看内核日志

使用dmesg查看是否有我们的日志输出:

adb shell dmesg | grep InitTest

预期输出:

<info>[ 5.123456] InitTest: 开机启动脚本已执行

7.3 方法三:使用 logcat 查看日志

因为我们用了log -t命令,所以也能在 logcat 中看到:

adb logcat -s InitTest

输出类似:

I/InitTest( 1234): 开机启动脚本已执行

7.4 方法四:串口日志(高级调试)

如果有串口调试工具,可以在早期阶段看到init解析.rc和执行脚本的过程。当出现如下错误时,基本可以定位问题:

init: Unable to spawn service 'test_service'... Permission denied

这通常是 SELinux 上下文不匹配导致的。


8. 常见问题与解决方案

8.1 脚本没执行,没有任何反应

可能原因

  • .rc文件未被加载
  • 路径拼写错误(大小写、斜杠)
  • 脚本没有放入最终镜像

排查方法

  • adb shell ls /system/bin/init.test.sh看是否存在
  • adb shell getprop ro.product.device确认.rc是否针对当前设备加载
  • 检查 build log 是否包含你的脚本模块

8.2 提示 “Permission denied” 或 SELinux 报错

典型日志

avc: denied { execute } for comm="init" name="init.test.sh" dev="sdaXX" scontext=u:r:init:s0 tcontext=u:object_r:system_file:s0 tclass=file

解决办法

  • 确保file_contexts正确映射了文件路径和类型
  • 确保.te文件中定义了exec_type
  • 使用permissive test_service;临时放开策略测试(仅调试用)

8.3 脚本反复重启(未加 oneshot)

如果你忘了加oneshotinit会认为服务异常退出并不断重启。

加上oneshot后,执行完即结束,不会重复运行。

8.4 脚本执行太早,依赖的服务还没起来

有些操作需要等到特定属性设置后才执行,可以用on property:触发:

on property:sys.usb.config=adb exec u:object_r:test_service_exec:s0 root root -- /system/bin/init.test.sh

或者监听boot_completed

on property:sys.boot_completed=1 start test_service

配合disabled使用更灵活:

service test_service /system/bin/init.test.sh class main user root group root oneshot disabled seclabel u:object_r:test_service_exec:s0

9. 最佳实践建议

9.1 小心使用 root 权限

尽量避免长期以 root 身份运行服务。如果只是初始化配置,完全可以执行完就退出。

9.2 日志先行,结果可验

每次调试都加一条logsetprop,确保你能通过外部手段验证执行状态。

9.3 使用专用命名空间

不要用test_service这种通用名,建议加上公司或项目前缀:

mycompany_init_service

避免与其他模块冲突。

9.4 脚本尽量简洁

.rc启动的脚本应专注于“初始化”,不要做耗时操作或网络请求。复杂逻辑建议交给后续服务处理。


10. 总结

通过本文的详细步骤,你应该已经掌握了如何在 Android 系统中实现一个可靠的开机启动 shell 脚本。回顾一下关键点:

  1. 编写正确的 shell 脚本,shebang 路径不能错
  2. 将脚本编译进系统镜像,并赋予可执行权限
  3. .rc文件中定义service并设置oneshotseclabel
  4. 添加 SELinux 策略(.te+file_contexts),这是成败关键
  5. 通过getproplogcatdmesg等方式验证执行结果

虽然整个过程涉及多个系统组件(init、SELinux、build 系统),但只要按部就班操作,完全可以掌握这一核心技能。

无论是做 ROM 定制、自动化测试还是硬件适配,这项能力都会成为你手中的一把利器。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/20 19:18:45

6步打造专业音质:音频均衡器完全指南

6步打造专业音质&#xff1a;音频均衡器完全指南 【免费下载链接】equalizerapo Equalizer APO mirror 项目地址: https://gitcode.com/gh_mirrors/eq/equalizerapo 音频均衡器是音效优化的核心工具&#xff0c;能够通过调整不同频率的声音强度&#xff0c;实现音质调校…

作者头像 李华
网站建设 2026/9/20 19:18:51

3大核心技术打造专业调音:Equalizer APO音质优化实战指南

3大核心技术打造专业调音&#xff1a;Equalizer APO音质优化实战指南 【免费下载链接】equalizerapo Equalizer APO mirror 项目地址: https://gitcode.com/gh_mirrors/eq/equalizerapo 音频均衡器设置是提升音质的关键步骤&#xff0c;通过专业的音效调节教程可以让普通…

作者头像 李华
网站建设 2026/9/24 2:34:16

电商数据采集工具实战指南:6大高效采集技巧助力自动化信息爬取

电商数据采集工具实战指南&#xff1a;6大高效采集技巧助力自动化信息爬取 【免费下载链接】xianyu_spider 闲鱼APP数据爬虫 项目地址: https://gitcode.com/gh_mirrors/xia/xianyu_spider 价值定位&#xff1a;重新定义电商数据采集的核心价值 在数字化商业时代&#…

作者头像 李华
网站建设 2026/9/24 4:43:20

IQuest-Coder-V1低成本部署:中小企业AI编码转型方案

IQuest-Coder-V1低成本部署&#xff1a;中小企业AI编码转型方案 1. 为什么中小企业需要自己的AI编程助手&#xff1f; 你是不是也遇到过这些情况&#xff1f; 团队里只有1-2个资深开发&#xff0c;却要同时维护3个老系统、响应5个业务部门的需求、还要抽空写技术文档&#x…

作者头像 李华
网站建设 2026/9/24 4:43:09

KKManager完全掌握手册:从入门到精通的模块化管理方案

KKManager完全掌握手册&#xff1a;从入门到精通的模块化管理方案 【免费下载链接】KKManager Mod, plugin and card manager for games by Illusion that use BepInEx 项目地址: https://gitcode.com/gh_mirrors/kk/KKManager 1. 问题诊断&#xff1a;模组管理常见痛点…

作者头像 李华
网站建设 2026/9/24 5:26:01

指令定制玩法:Qwen3-Embedding-0.6B个性化任务设置

指令定制玩法&#xff1a;Qwen3-Embedding-0.6B个性化任务设置 嵌入模型不是“一锤定音”的黑箱&#xff0c;而是可塑性强、响应灵敏的语义引擎。当你不再满足于默认的“把句子变成向量”&#xff0c;而是希望它理解“这是客服工单”“这是代码注释”“这是小红书种草文案”—…

作者头像 李华