Android 8.0开机启动脚本实战,一键部署方案

Android 8.0开机启动脚本实战:一键部署方案

在Android系统定制开发中,让自定义服务或脚本随系统启动自动运行,是嵌入式工程师和OEM厂商的常见需求。尤其在工业终端、车载设备、智能硬件等场景中,开机即启动数据采集、网络配置、外设初始化等任务,直接关系到产品可用性与用户体验。

但Android 8.0(Oreo)引入了更严格的init机制和SELinux强制访问控制策略,传统Linux下的rc.local方式已完全失效。很多开发者照搬旧方法后发现脚本“写好了却没执行”“属性设置了却查不到”“日志里全是avc denied”,最终卡在权限、路径、上下文三重门槛上。

本文不讲抽象原理,不堆砌SELinux术语,而是基于真实MTK平台适配经验,为你梳理一套可验证、可复用、可一键部署的开机启动脚本落地方案。所有步骤均已在Android 8.0真机环境实测通过,覆盖从脚本编写、SELinux策略配置、init.rc集成到快速验证的完整闭环。

你不需要提前了解SELinux策略语法,也不必深究init进程启动流程——只要按顺序操作,就能让自己的shell脚本在系统就绪后第一时刻安静而稳定地跑起来。


1. 明确目标与前置条件

1.1 本次实践要达成什么

  • 编写一个功能明确的开机启动shell脚本(如设置系统属性、创建测试文件、启动后台服务)
  • 将脚本正确部署到/system/bin/目录并赋予可执行权限
  • 为脚本定义专属SELinux类型与执行上下文
  • 在init系统中注册service,并指定其启动时机与执行身份
  • 验证脚本是否真正执行(通过getproplogcatls等命令确认)

注意:本文不涉及关闭SELinux(setenforce 0)或修改ro.build.selinux=0等规避手段。所有操作均在Enforcing模式下完成,符合Android安全规范。

1.2 你需要准备什么

项目要求说明
设备已解锁Bootloader、支持adb root的Android 8.0设备(推荐MTK/高通公版ROM)真机调试优于模拟器,因init.rc和SELinux策略在模拟器中行为受限
开发环境Linux/macOS主机 + ADB工具 + root权限Windows用户建议使用WSL2
构建环境(可选)Android源码树(仅需修改时)若仅做单次验证,可跳过编译,用adb push+临时挂载方式

1.3 为什么必须是Android 8.0?关键变化在哪

Android 8.0对init系统做了重大重构:

  • init.rc被拆分为多个模块化.rc文件(如init.mt6765.rcinit.vendor.rc),不再允许直接修改主init.rc
  • 所有service默认以user systemgroup system运行,root权限需显式声明
  • SELinux策略由sepolicy统一管理,file_contexts中未声明的路径将继承父目录上下文,导致执行失败
  • oneshot服务执行完毕即退出,适合一次性脚本;disabled服务需手动触发,适合守护进程

这些变化意味着:过去在Android 5.x/6.x上能跑通的脚本,在8.0上90%会静默失败。不是脚本错了,而是系统“不认识它”。


2. 四步落地:从脚本到开机执行

我们把整个流程压缩为四个清晰、可验证的步骤。每一步都附带验证方法,避免“以为成功,实则失败”。

2.1 第一步:编写可验证的启动脚本

新建文件init.test.sh,内容如下:

#!/system/bin/sh # 注意:Android 8.0必须使用 /system/bin/sh,不可用 /bin/sh 或 /system/xbin/sh(部分ROM无此路径) # 设置一个易检测的系统属性(比写文件更轻量、更可靠) setprop vendor.test.booted 1 # 记录时间戳到tmp目录(验证是否执行) echo "booted at $(date)" > /data/local/tmp/boot_test.log # 可选:启动一个简单后台进程(如ping网关,用于后续ps检查) # nohup ping -c 3 192.168.1.1 > /dev/null 2>&1 &

验证要点

  • 保存后,用chmod +x init.test.sh赋予可执行权限
  • 通过adb push init.test.sh /data/local/tmp/推送至设备
  • 执行adb shell "sh /data/local/tmp/init.test.sh"
  • 检查:adb shell getprop vendor.test.booted应返回1adb shell cat /data/local/tmp/boot_test.log应显示时间戳

这一步确保脚本逻辑正确、语法无误、路径可写。跳过此步直接进init,90%问题源于脚本本身

2.2 第二步:定义SELinux类型与文件上下文

Android 8.0要求每个可执行文件必须有明确的SELinux类型(type)和上下文(context)。否则,即使脚本存在,init也会因权限拒绝而跳过执行。

创建类型定义文件test_service.te

在你的SELinux策略目录(如device/mediatek/sepolicy/basic/non_plat/)下新建test_service.te

# 定义服务域类型 type test_service, domain; type test_service_exec, exec_type, file_type; # 允许该域由init_daemon_domain启动 init_daemon_domain(test_service); # 允许test_service读取/执行自身文件 allow test_service test_service_exec:file { read open getattr execute }; # 允许向property_service写入vendor.*属性(关键!) allow test_service property_service:property_service set;

注意:

  • type test_service, domain;表示这是一个独立的执行域,而非coredomain(后者权限过大,不符合最小权限原则)
  • allow ... set;是设置vendor.test.booted属性所必需的,漏掉将导致setprop静默失败
声明文件上下文file_contexts

在同一目录的file_contexts文件末尾添加一行:

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

验证要点

  • 修改后需重新编译sepolicy(m sepolicy)并刷入boot.img或vendor.img
  • 刷机后执行adb shell ls -Z /system/bin/init.test.sh,输出应包含u:object_r:test_service_exec:s0
  • 若显示u:object_r:shell_exec:s0或其他类型,则上下文未生效

此步确保系统“认识”你的脚本,并赋予其最小必要权限。

2.3 第三步:在init中注册service

Android 8.0禁止直接修改/system/etc/init.rc。正确做法是:在芯片平台专用的init.rc文件中添加service声明

查找你的平台init.rc文件

常见路径(根据芯片平台选择其一):

  • MTK:device/mediatek/sepolicy/basic/non_plat/init.mt6765.rc(以实际芯片名为准)
  • 高通:device/qcom/common/init.qcom.rc
  • 其他:搜索init.*.rc或查看BoardConfig.mkBOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD相关配置
添加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:表示该service属于main类,将在on early-init之后、on init阶段启动
  • user root&group root:显式声明以root身份运行(默认为system)
  • oneshot:执行完即退出,适合初始化类脚本;若需常驻,请改用disabled+start xxx触发
  • seclabel:必须与file_contexts中定义的上下文严格一致

此步确保init进程“知道”何时、以何种身份、用什么上下文去执行你的脚本。

2.4 第四步:部署与验证全流程

完成上述三步后,进入最终部署环节。我们提供两种方式,适配不同开发阶段:

方式A:源码编译部署(推荐用于量产/长期维护)
  1. init.test.sh放入system/extras/目录(或自定义路径)
  2. Android.mk中添加安装规则:
    LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := init.test.sh LOCAL_MODULE_TAGS := optional LOCAL_MODULE_CLASS := EXECUTABLES LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES) LOCAL_SRC_FILES := init.test.sh include $(BUILD_PREBUILT)
  3. 编译system.img:m systemimage
  4. 刷入设备并重启
方式B:ADB临时部署(推荐用于快速验证)

注意:需先remount/system为可写(仅限已root设备)

# 1. 挂载system为可写 adb root adb remount # 2. 推送脚本并赋权 adb push init.test.sh /system/bin/ adb shell chmod 755 /system/bin/init.test.sh # 3. 重启设备 adb reboot
验证是否成功执行

设备重启后,立即执行以下命令:

# 检查属性是否设置成功 adb shell getprop vendor.test.booted # 应输出 1 # 检查日志文件是否存在且有内容 adb shell cat /data/local/tmp/boot_test.log # 检查init service状态(需root) adb shell "ls -l /dev/android_boot_complete" # 若存在,说明main class已启动 adb shell "ps | grep test_service" # 应无残留进程(因oneshot) # 查看init日志(关键!) adb logcat -b events | grep "test_service" # 正常输出类似:init: starting service 'test_service'...

若以上全部通过,恭喜你,开机启动脚本已稳定运行。


3. 常见问题与避坑指南

实际部署中,以下问题出现频率最高。我们按现象归类,给出直击根源的解决方案。

3.1 脚本根本没执行:init日志无记录

现象最可能原因解决方案
logcat -b events中完全搜不到test_serviceservice未被init加载检查.rc文件路径是否正确;确认class main是否拼写错误;用adb shell cat /proc/1/cmdline确认init进程加载的rc文件列表
日志显示Could not create service 'test_service'/system/bin/init.test.sh不存在或权限不足adb shell ls -l /system/bin/init.test.sh,确认存在且权限为-rwxr-xr-x
日志显示Failed to set context for '/system/bin/init.test.sh'file_contexts未生效或路径匹配失败检查正则表达式是否转义了.(应为\.),确认sepolicy已重新编译刷入

3.2 脚本执行了但效果异常

现象最可能原因解决方案
getprop vendor.test.booted返回空SELinux拒绝property写入test_service.te中补全allow test_service property_service:property_service set;并重刷sepolicy
/data/local/tmp/boot_test.log为空或报错脚本内路径不可写Android 8.0默认限制/data下部分子目录写入;改用/data/misc//data/vendor/(需额外SELinux权限)
脚本中ping等命令提示not foundBusyBox未预装或PATH不包含/system/xbin在脚本开头添加export PATH=/system/bin:/system/xbin:$PATH

3.3 SELinux avc denied 报错分析

dmesglogcat -b kernel中出现类似:

avc: denied { set } for property="vendor.test.booted" scontext=u:r:test_service:s0 tcontext=u:object_r:default_prop:s0 tclass=property_service

这表示SELinux策略缺失。不要盲目添加permissive test_service;,而应:

  1. 记录完整avc行(含scontexttcontexttclass{ action }
  2. 根据{ set }tclass=property_service,在test_service.te中添加对应allow规则
  3. 重新编译sepolicy并验证

提示:可使用audit2allow -i dmesg.log -p policy.conf辅助生成规则(需完整sepolicy源码)


4. 进阶技巧:让启动更可靠、更灵活

掌握基础后,可进一步提升脚本健壮性与工程实用性。

4.1 使用wait_for_prop实现依赖等待

某些服务需等待系统属性就绪后再启动。例如,等待sys.boot_completed=1

#!/system/bin/sh # 等待系统完全启动完成(超时30秒) /wait_for_prop sys.boot_completed 1 30 # 此时再执行业务逻辑 setprop vendor.test.ready 1

4.2 用start/stop控制service生命周期

oneshot改为disabled,并在需要时手动触发:

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

然后在其他service中通过start test_service调用,或通过adb shell start test_service调试。

4.3 日志集中管理:重定向到logcat

避免写文件,直接输出到Android日志系统:

#!/system/bin/sh log -p i -t TEST_BOOT "Service started" setprop vendor.test.booted 1 log -p i -t TEST_BOOT "Property set successfully"

log命令是Android内置工具,无需额外依赖,输出可通过adb logcat -s TEST_BOOT实时查看。


5. 总结:一条可复用的开机启动路径

回顾整个流程,我们构建了一条零妥协、可验证、易维护的Android 8.0开机启动路径:

  • 脚本层:用/system/bin/sh编写,以setprop为黄金验证点,轻量可靠;
  • SELinux层:定义专属domainexec_type,精确授权property_service set,拒绝宽泛permissive
  • init层:在平台专属.rc中声明service,显式指定user rootseclabel,严守Android 8.0规范;
  • 验证层:组合getproplogcat -b eventsls -Z三重检查,确保每一步真实生效。

这不是一份“理论上可行”的教程,而是从产线踩坑中提炼出的最小可行方案。你完全可以将init.test.sh替换为任何业务脚本——初始化GPIO、加载固件、上报设备ID、启动看门狗……只要遵循这套结构,就能在Android 8.0上稳定运行。

下一步,你可以尝试将此方案封装为Yocto recipe、或集成进CI/CD流水线,实现“一次配置,多平台复用”。

--- > **获取更多AI镜像** > > 想探索更多AI镜像和应用场景?访问 [CSDN星图镜像广场](https://ai.csdn.net/?utm_source=mirror_blog_end),提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1212279.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

3大突破!如何破解VMProtect加密壁垒:VMPDump动态脱壳工具全解析

3大突破!如何破解VMProtect加密壁垒:VMPDump动态脱壳工具全解析 【免费下载链接】vmpdump A dynamic VMP dumper and import fixer, powered by VTIL. 项目地址: https://gitcode.com/gh_mirrors/vm/vmpdump VMPDump是一款基于VTIL框架开发的动态…

零基础入门Qwen3-1.7B,手把手教你调用大模型API

零基础入门Qwen3-1.7B,手把手教你调用大模型API 你是不是也遇到过这些情况: 想试试最新的大模型,但看到“CUDA”“vLLM”“LoRA微调”就头皮发麻? 下载完镜像,打开Jupyter却卡在第一步——连模型怎么“打招呼”都不知…

【实战】3天掌握OSTrack目标跟踪:从零基础到模型部署全攻略

【实战】3天掌握OSTrack目标跟踪:从零基础到模型部署全攻略 【免费下载链接】OSTrack [ECCV 2022] Joint Feature Learning and Relation Modeling for Tracking: A One-Stream Framework 项目地址: https://gitcode.com/gh_mirrors/os/OSTrack 一、技术价值…

基于Spring Ai的Agent 工程师

基于Spring Ai的Agent 工程师 一、基础概念题 1. 什么是 Spring AI?它的核心定位是什么? 答案: Spring AI 是 Spring 生态的 AI 应用开发框架,旨在简化 Java 开发者构建 AI 应用的过程核心定位:“AI 应用的 Spring …

Multisim示波器使用测量光标操作指南

以下是对您提供的博文内容进行 深度润色与结构重构后的技术文章 。全文已彻底去除AI生成痕迹,采用资深嵌入式系统教学博主的自然语言风格——逻辑层层递进、讲解深入浅出、案例真实可感,兼具专业性与可读性。文中所有技术点均基于Multisim官方文档与工程实践验证,无虚构参…

5个步骤掌握newbee-mall-api:Spring Boot电商API开发指南

5个步骤掌握newbee-mall-api:Spring Boot电商API开发指南 【免费下载链接】newbee-mall-api 🔥 🎉新蜂商城前后端分离版本-后端API源码 项目地址: https://gitcode.com/gh_mirrors/ne/newbee-mall-api 新蜂商城(newbee-mal…

快速上手Qwen2.5-7B微调,附完整命令清单

快速上手Qwen2.5-7B微调,附完整命令清单 1. 为什么这次微调真的只要十分钟? 你可能已经试过很多次大模型微调——下载依赖、配置环境、调试报错、显存爆炸……最后放弃。但这次不一样。 这个镜像不是“理论上能跑”,而是在 RTX 4090D&…

ModbusRTU现场调试记录:常见波形异常图解说明

以下是对您提供的博文《ModbusRTU现场调试记录:典型波形异常的深度技术解析》进行 全面润色与专业重构后的终稿 。本次优化严格遵循您的全部要求: ✅ 彻底去除AI痕迹,语言自然、老练、有工程师体温; ✅ 摒弃所有模板化标题(如“引言”“总结”“展望”),全文以逻辑流…

7天从零到实战:如何用PyTorch WaveNet开启音频AI创作之旅?

7天从零到实战:如何用PyTorch WaveNet开启音频AI创作之旅? 【免费下载链接】pytorch-wavenet 项目地址: https://gitcode.com/gh_mirrors/py/pytorch-wavenet 一、认知篇:走进音频生成的奇妙世界 1.1 什么是WaveNet?为什…

智能机械设计工具:重新定义工程图纸自动化流程

智能机械设计工具:重新定义工程图纸自动化流程 【免费下载链接】text-to-cad-ui A lightweight UI for interfacing with the Zoo text-to-cad API, built with SvelteKit. 项目地址: https://gitcode.com/gh_mirrors/te/text-to-cad-ui 为什么80%的工程师仍…

隐私更安全!本地化AI手机助手搭建全过程

隐私更安全!本地化AI手机助手搭建全过程 摘要:本文手把手带你用Mac或Windows电脑,完全离线部署智谱开源的Open-AutoGLM手机AI助理框架。不上传截图、不依赖云端API、不泄露操作记录——所有数据始终留在你自己的设备上。从零开始连接真机、下…

低代码流程引擎解决方案:bpmn-vue-activiti赋能开发者的业务流程自动化工具

低代码流程引擎解决方案:bpmn-vue-activiti赋能开发者的业务流程自动化工具 【免费下载链接】bpmn-vue-activiti 基于Vue3.x Vite bpmn-js element-plus tsx 实现的Activiti流程设计器(Activiti process designer based on Vue3.x Vite BPMN-JS Element-Plus…

Paraformer-large推理速度慢?Batch Size调优实战教程揭秘

Paraformer-large推理速度慢?Batch Size调优实战教程揭秘 你是不是也遇到过这样的情况:明明用的是4090D显卡,Paraformer-large模型加载成功、Gradio界面也跑起来了,可一上传3分钟的录音,转写却要等20秒以上&#xff1…

3个实用方案:解决MacBook合盖不休眠的技术指南

3个实用方案:解决MacBook合盖不休眠的技术指南 【免费下载链接】nosleep The MacOS X kernel extension, preventing sleep when you close the lid. 项目地址: https://gitcode.com/gh_mirrors/no/nosleep 当你将MacBook连接到外接显示器想要扩展工作空间时…

Windows下Synaptics驱动配置完整指南

以下是对您提供的技术博文进行 深度润色与专业重构后的版本 。我以一名嵌入式系统驱动工程师兼Windows内核调试老手的身份,用更自然、更具实战感的语言重写了全文——摒弃AI腔调和模板化结构,强化逻辑递进、经验沉淀与可操作性,同时严格遵循您提出的全部格式与风格要求(无…

Qwen3-Embedding-0.6B开发者指南:API接口调试与错误码解析

Qwen3-Embedding-0.6B开发者指南:API接口调试与错误码解析 你是不是也遇到过这样的情况:模型明明启动成功了,调用时却返回一串看不懂的报错;明明输入了正确的URL和参数,结果提示“model not found”或者“invalid req…

cv_unet_image-matting如何实现主题色替换?背景颜色批量设置

cv_unet_image-matting如何实现主题色替换?背景颜色批量设置 1. 从抠图到主题色替换:为什么这个功能如此实用? 你有没有遇到过这样的场景:刚做完一批人像抠图,结果客户突然说“背景要换成品牌蓝”,或者“…

Warcraft Font Merger:开源字体优化工具的技术解决方案

Warcraft Font Merger:开源字体优化工具的技术解决方案 【免费下载链接】Warcraft-Font-Merger Warcraft Font Merger,魔兽世界字体合并/补全工具。 项目地址: https://gitcode.com/gh_mirrors/wa/Warcraft-Font-Merger 在游戏本地化过程中&#…

Live Avatar服装生成:red dress提示词工程技巧

Live Avatar服装生成:red dress提示词工程技巧 1. 什么是Live Avatar?数字人技术的新突破 Live Avatar是由阿里联合高校开源的数字人生成模型,它能将静态人像、语音和文本提示词融合,实时生成高质量的说话视频。不同于传统数字人需…

GPEN镜像输出效果惊艳,连发丝都清晰可见

GPEN镜像输出效果惊艳,连发丝都清晰可见 你有没有试过放大一张模糊的人脸照片,结果只看到一片马赛克?或者在老照片修复时,反复调整参数却始终无法让睫毛、发丝这些细节自然重现?这次我们实测的GPEN人像修复增强模型镜…