news 2026/5/14 3:57:44

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/5/10 11:08:36

3步掌握轻量级AI模型MobileSAM:从原理到移动端部署的实战指南

3步掌握轻量级AI模型MobileSAM:从原理到移动端部署的实战指南 【免费下载链接】MobileSAM This is the official code for MobileSAM project that makes SAM lightweight for mobile applications and beyond! 项目地址: https://gitcode.com/gh_mirrors/mo/Mobi…

作者头像 李华
网站建设 2026/5/10 8:53:42

GPEN人像增强 vs 传统算法,清晰度对比实测

GPEN人像增强 vs 传统算法,清晰度对比实测 你有没有试过翻出十年前的老照片——泛黄、模糊、带着噪点,想发朋友圈却不敢发?或者客户甩来一张手机远距离偷拍的证件照,像素糊得连眼睛都分不清?这时候你会怎么做&#xf…

作者头像 李华
网站建设 2026/5/10 3:33:07

Windows 11安装TPM绕过工具使用指南:老电脑升级全流程解析

Windows 11安装TPM绕过工具使用指南:老电脑升级全流程解析 【免费下载链接】rufus The Reliable USB Formatting Utility 项目地址: https://gitcode.com/GitHub_Trending/ru/rufus 随着Windows 11系统的普及,许多用户面临着硬件限制的困扰。本文…

作者头像 李华
网站建设 2026/5/10 13:10:24

4步解锁Wii U游戏电脑运行:Cemu模拟器全方位实战指南

4步解锁Wii U游戏电脑运行:Cemu模拟器全方位实战指南 【免费下载链接】yuzu 任天堂 Switch 模拟器 项目地址: https://gitcode.com/GitHub_Trending/yu/yuzu 1.彻底搞懂Cemu模拟器:从入门到进阶 1.1什么是Cemu模拟器? Cemu → 一款专…

作者头像 李华
网站建设 2026/5/9 13:51:21

rs232串口通信原理图入门指南:掌握基本结构与元件作用

以下是对您提供的博文内容进行 深度润色与专业重构后的版本 。整体风格更贴近一位资深嵌入式硬件工程师在技术社区中自然、扎实、有温度的分享——去除了模板化表达、AI腔调和冗余结构,强化了逻辑递进、工程直觉与实战细节,同时严格遵循您提出的全部格式与语言规范(无“引…

作者头像 李华
网站建设 2026/5/12 8:58:46

Qwen3-1.7B语音助手后端:ASR+NLP联合部署案例

Qwen3-1.7B语音助手后端:ASRNLP联合部署案例 你是否试过用一句话唤醒智能助手,让它听懂你的指令、理解语义、再给出精准回应?这不是科幻电影里的桥段——今天我们就用一个轻量但实用的组合:ASR语音识别 Qwen3-1.7B语言模型&…

作者头像 李华