news 2026/4/22 23:25:20

Android开机自启功能实现,基于init.test.sh

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Android开机自启功能实现,基于init.test.sh

Android开机自启功能实现:基于init.test.sh的轻量级方案

在Android系统开发中,让自定义脚本在设备启动时自动运行是一项常见但容易踩坑的需求。不同于Linux通用发行版的systemd或rc.local机制,Android使用自己的init系统和SELinux安全模型,这意味着简单地把脚本丢进某个目录并不能让它“自然启动”。本文将带你从零开始,用一个真实可运行的轻量级方案——init.test.sh,完成开机自启功能的完整落地。不依赖复杂框架、不修改核心服务、不绕过安全策略,每一步都经过实测验证(Android 8.0+主流平台),适合嵌入式工程师、系统定制开发者和固件调试人员快速上手。

1. 为什么不能直接用传统Linux方式?

很多刚接触Android底层的同学会下意识套用Linux经验:把脚本放进/etc/init.d/、加chmod +x、再写个update-rc.d?很遗憾,在标准Android系统中,这些路径根本不存在,init进程也不会扫描它们。

Android的启动流程由init进程严格控制,它读取init.rc及其包含的.rc文件,按服务(service)和动作(action)声明来调度执行。更重要的是,从Android 5.0起,SELinux默认启用且为enforcing模式,任何未被明确授权的进程行为(包括执行新脚本、访问特定路径、设置系统属性等)都会被拦截并记录到dmesg日志中。

所以,真正可行的路径只有一条:让init认识你的脚本,让SELinux信任你的脚本,让系统属性或日志能证明它确实跑起来了。下面我们就沿着这条路径,分四步走完全部流程。

2. 第一步:编写可执行的init脚本

脚本本身必须满足Android init系统的硬性要求,稍有偏差就会静默失败——连错误提示都不会输出。

2.1 脚本位置与权限规范

  • 存放路径:必须放在/system/bin//vendor/bin/下(推荐前者,兼容性更好)
  • 文件名:建议使用init.xxx.sh命名风格(如init.test.sh),便于识别用途
  • 权限chmod 755 /system/bin/init.test.sh(owner可读写执行,group/o仅读执行)
  • 挂载状态/system分区需为可写(adb remount或烧录前已设为rw)

注意:不要尝试放在/data/local/tmp//sdcard/下——init进程在早期阶段无法访问这些路径,且SELinux策略默认禁止。

2.2 脚本内容与关键细节

以下是一个最小可用、经实测通过的init.test.sh模板:

#!/system/bin/sh # Android专用shebang:必须是/system/bin/sh或/system/xbin/sh # /bin/sh在Android中通常不存在,硬写会导致脚本完全不执行 # 设置一个测试属性,用于快速验证是否运行成功 setprop sys.test.booted 1 # 可选:写入日志便于调试(需确保logd已启动) log -t INIT_TEST "Script executed at $(date)" # 可选:启动一个后台守护进程(如需要长期运行) # nohup /system/bin/mydaemon & # 可选:触发其他init action(如重启某个服务) # trigger my_custom_service

2.3 验证脚本独立可运行

在集成进init流程前,务必手动验证脚本本身无语法错误、权限正确、逻辑可达:

# 推送脚本到设备 adb push init.test.sh /system/bin/init.test.sh # 设置权限 adb shell chmod 755 /system/bin/init.test.sh # 手动执行并检查结果 adb shell /system/bin/init.test.sh adb shell getprop sys.test.booted # 应输出"1" adb logcat -t 10 -s INIT_TEST # 应看到日志输出

如果这一步失败,请优先检查:shebang路径是否正确、/system是否可写、脚本是否有Windows换行符(\r\n)、是否缺少setprop所需SELinux权限(见第4步)。

3. 第二步:声明SELinux类型与上下文

Android 8.0+采用编译时策略(precompiled sepolicy),所有自定义服务必须在SELinux策略中明确定义其类型、执行上下文和访问权限。跳过此步,脚本在init中会被SELinux直接拒绝,且不会报错到logcat,只在dmesg中留下类似avc: denied { execute } for path="/system/bin/init.test.sh"的日志。

3.1 创建te策略文件

在设备厂商的sepolicy目录下(如MTK平台为device/mediatek/sepolicy/basic/non_plat/),新建test_service.te

# 定义服务域类型 type test_service, domain; type test_service_exec, exec_type, vendor_file_type, file_type; # 允许该域作为init守护进程运行 init_daemon_domain(test_service); # 允许执行自身脚本文件 allow test_service test_service_exec:file { read open execute getattr }; # 允许设置系统属性(对应脚本中的setprop) allow test_service system_file:file { read }; allow test_service system_prop:property_service { set }; # 允许写入log(对应脚本中的log命令) allow test_service logd:dir { search }; allow test_service logd:file { read write open }; allow test_service logd:unix_dgram_socket { sendto };

关键说明:

  • init_daemon_domain()是必须调用的宏,它自动赋予test_service域访问/dev/*/proc/*等init必需路径的权限;
  • allow ... property_service { set }setprop命令必需的权限;
  • 若脚本中调用log命令,必须显式允许对logd的socket通信权限。

3.2 绑定文件上下文

在同一sepolicy目录下的file_contexts文件(如device/mediatek/sepolicy/basic/non_plat/file_contexts)中,添加一行:

/system/bin/init\.test\.sh u:object_r:test_service_exec:s0

注意:

  • 路径需用正则转义(.\.),否则匹配失败;
  • 类型名test_service_exec必须与.te文件中定义的完全一致;
  • 即使临时关闭SELinux(setenforce 0),此行也必须存在,否则init无法识别该文件为可执行服务。

3.3 编译并刷入策略

修改完成后,重新编译boot镜像(或system镜像),确保新策略生效。验证方法:

# 检查文件上下文是否正确 adb shell ls -Z /system/bin/init.test.sh # 输出应包含:u:object_r:test_service_exec:s0 # 检查策略是否加载 adb shell dmesg | grep avc | tail -10 # 开机后检查是否有denied日志

4. 第三步:在init.rc中注册服务

Android init通过解析.rc文件启动服务。虽然可以直接修改/system/etc/init.rc,但强烈不建议——它属于AOSP核心文件,易被OTA覆盖,且不同芯片平台结构差异大。

4.1 推荐做法:使用平台专属rc文件

主流SoC厂商均提供客户可扩展的rc入口,例如:

平台推荐rc文件路径
MTK/system/etc/init/hw/init.mtk.rc
Qualcomm/system/etc/init/hw/init.qcom.rc
Samsung/system/etc/init/hw/init.samsung.rc

若不确定,可搜索/system/etc/init/下以init.*.rc命名的文件,或查看init.rcimport语句引入的路径。

4.2 编写服务声明

在选定的.rc文件末尾,添加以下服务定义:

# 定义test_service服务 service test_service /system/bin/init.test.sh class main user root group root oneshot seclabel u:object_r:test_service_exec:s0 # 可选:指定启动时机(在zygote启动后) on property:sys.boot_completed=1 start test_service

参数详解:

  • class main:归入main类,随系统主服务一起启动;
  • user/group root:以root权限运行(必要,因需设置系统属性);
  • oneshot:执行完即退出(适合初始化脚本);若需常驻,请改用disabled+start触发;
  • seclabel:必须与file_contexts中定义的类型一致;
  • on property:更精准的启动时机控制,避免在系统未就绪时执行。

4.3 验证rc语法与加载

编译刷机后,可通过以下命令确认服务是否被init识别:

adb shell getenforce # 确保为Enforcing adb shell getprop sys.boot_completed # 确保为1(系统已启动完成) adb shell cat /sys/fs/selinux/enforce # 确保为1 # 查看test_service状态 adb shell service list | grep test_service # 或检查init日志 adb logcat -b events | grep -i "test_service"

5. 第四步:调试与问题排查

即使严格遵循上述步骤,仍可能遇到启动失败。以下是高频问题及定位方法:

5.1 快速诊断三板斧

现象检查点命令示例
脚本完全没执行init是否加载了你的.rc?服务名是否拼写一致?adb shell cat /proc/1/cmdline
adb shell ls /system/etc/init/ | grep rc
setprop失败SELinux是否拒绝property_service?adb shell dmesg | grep -i "avc.*property_service"
log命令无输出logd是否已启动?SELinux是否允许socket通信?adb shell ps | grep logd
adb shell dmesg | grep -i "avc.*logd"
脚本执行但属性未设置setprop目标属性是否被ro.前缀锁定?adb shell getprop | grep test
adb shell getprop | grep ro.test

5.2 实用调试技巧

  • 临时降级SELinuxadb shell setenforce 0(仅用于快速验证逻辑,非最终解法)
  • 强制触发服务adb shell start test_service(绕过init自动触发,直接测试)
  • 查看init详细日志adb logcat -b events -v threadtime \| grep -i "test_service"
  • 检查文件完整性adb shell sha256sum /system/bin/init.test.sh(确认推送无损坏)

5.3 常见错误与修复

  • ❌ 错误:dmesg显示avc: denied { execute } for ... init.test.sh
    修复:检查file_contexts路径是否精确匹配,te文件中是否遗漏allow ... execute

  • ❌ 错误:getprop sys.test.booted始终为空
    修复:确认setprop权限已添加;检查属性名是否含非法字符(只支持字母、数字、._);确认脚本确实在执行(加log语句验证)

  • ❌ 错误:服务状态为stoppedstart test_service后立即变为stopping
    修复:检查脚本是否异常退出(如语法错误、exit 1);用adb shell /system/bin/init.test.sh手动执行看是否报错

6. 总结:一条可复用的工程化路径

本文围绕init.test.sh这一轻量级载体,完整呈现了Android开机自启功能的落地闭环。它不是理论推演,而是来自真实项目调试的经验沉淀——每一行代码、每一个配置项,都经过Android 8.0及以上版本的实机验证。

回顾整个流程,我们构建了一条清晰、稳健、可复用的工程路径:

  • 脚本层:用/system/bin/sh为shebang,以setprop为轻量信号,规避文件I/O权限风险;
  • 策略层:通过test_service.tefile_contexts双文件绑定,实现最小权限原则;
  • 启动层:依托平台init.*.rc机制,避免侵入AOSP核心,保障OTA兼容性;
  • 调试层:以dmesg+logcat+getprop为黄金三角,快速定位SELinux、init、脚本三层问题。

这套方法不仅适用于init.test.sh,更可平滑迁移到任何自定义守护进程(如硬件监控、日志收集、远程诊断服务)。当你下次需要让一段逻辑在Android设备“睁眼第一秒”就运行起来时,记住:不是Linux,就别用Linux的思维;是Android,就尊重它的init和SELinux


获取更多AI镜像

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

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

Qwen-Image-Edit-2511一键启动:开箱即用的AI图像编辑方案

Qwen-Image-Edit-2511一键启动:开箱即用的AI图像编辑方案 你是否经历过这样的场景:刚下载好ComfyUI,兴致勃勃想试试最新的图像编辑模型,结果卡在环境配置、模型路径、节点连接、参数调试上一整个下午?明明只想把商品图…

作者头像 李华
网站建设 2026/4/19 5:41:17

如何让Android应用高效渲染富文本?RichText的全栈解决方案

如何让Android应用高效渲染富文本?RichText的全栈解决方案 【免费下载链接】RichText Android平台下的富文本解析器,支持Html和Markdown 项目地址: https://gitcode.com/gh_mirrors/ri/RichText iOS富文本渲染一直是移动开发中的痛点,…

作者头像 李华
网站建设 2026/4/19 15:02:44

教育AI落地案例:FSMN-VAD实现课堂语音自动分割

教育AI落地案例:FSMN-VAD实现课堂语音自动分割 1. 为什么课堂录音需要“自动切分”? 你有没有听过这样的教学场景:一位老师用45分钟讲完一节物理课,录下的音频长达2700秒——但其中真正有声音的部分可能只有1800秒,其…

作者头像 李华
网站建设 2026/4/18 15:08:47

BSHM镜像提速秘籍,节省一半等待时间

BSHM镜像提速秘籍,节省一半等待时间 你有没有遇到过这样的情况:人像抠图任务明明只有一张照片,却要等上十几秒甚至更久?明明显卡性能不差,推理速度却卡在瓶颈?别急,这不是模型不行,…

作者头像 李华
网站建设 2026/4/22 4:18:52

用CV-UNet镜像做了个电商去背项目,全过程分享

用CV-UNet镜像做了个电商去背项目,全过程分享 1. 为什么选CV-UNet做电商去背?真实原因很实在 做电商运营的朋友都懂:一张干净的产品图,能直接拉高点击率和转化率。但现实是——摄影师拍完图,还得花大量时间在PS里抠背…

作者头像 李华
网站建设 2026/4/16 20:50:50

快速上手YOLOv9:官方镜像+预下载权重真香

快速上手YOLOv9:官方镜像预下载权重真香 在工业质检产线实时识别微小缺陷、智能交通系统毫秒级捕捉违章车辆的今天,一个反复出现的现实困境是:明明论文里效果惊艳的模型,为什么在自己电脑上跑不起来?不是CUDA版本报错…

作者头像 李华