2026/4/18 7:24:26
网站建设
项目流程
网站建设的项目亮点怎么写,教育网站设制下载,网页设计按钮代码模板,大学个人网站期末作业小白也能懂的Android开机脚本部署#xff0c;保姆级教程
你是不是也遇到过这样的问题#xff1a; 想让Android设备一开机就自动执行某个任务——比如备份日志、启动监控服务、初始化硬件参数#xff0c;甚至只是简单地打个日志确认系统已就绪#xff1f;但一搜“Android开…小白也能懂的Android开机脚本部署保姆级教程你是不是也遇到过这样的问题想让Android设备一开机就自动执行某个任务——比如备份日志、启动监控服务、初始化硬件参数甚至只是简单地打个日志确认系统已就绪但一搜“Android开机启动”出来的全是init.rc、SELinux、te文件、file_contexts……每个词都像天书点开几篇博客还没看到效果就已经被权限报错、编译失败、selinux拒绝访问劝退了别急。这篇教程就是为你写的。它不假设你熟悉AOSP编译流程不要求你会写SELinux策略也不需要你有串口调试线或root过的工程机。我们用最贴近真实开发环境的方式从一个能跑通的最小闭环开始手把手带你把第一个开机脚本稳稳跑起来。过程中每一步为什么这么做、哪里容易出错、怎么快速验证都会说清楚。全文没有黑话不堆术语所有命令和配置都经过实测基于Android 8.0主流厂商平台关键步骤附截图逻辑示意文字描述版代码可直接复制粘贴改两处路径就能用。准备好了吗咱们现在就开始。1. 先搞明白Android开机脚本到底在哪个环节运行在动手写代码前得先知道“开机脚本”不是Linux里那种随便放/etc/rc.local就能跑的东西。Android有一套自己的初始化机制核心是init进程——它是系统中第一个用户态进程负责解析init.rc系列脚本拉起关键服务。而我们要插入的就是这个流程里的一个自定义服务service。它会在init完成基础初始化后、系统UI启动前以指定用户身份通常是root执行你的shell脚本。这个过程可以简化为四个必须连通的环节脚本本身一个符合Android shell规范的.sh文件可执行权限与位置放在/system/bin/或/vendor/bin/下并有正确SELinux上下文服务声明在init.xxx.rc中定义service块告诉init“这个脚本要什么时候、以谁的身份跑”SELinux放行让init进程有权限去执行这个脚本这是90%新手卡住的地方这四步缺一不可但顺序可以优化我们先做最易验证的——写脚本并手动运行再逐步接入开机流程。2. 第一步写出一个真正能跑通的开机脚本2.1 脚本内容极简但健壮新建一个文件命名为init.test.sh内容如下#!/system/bin/sh # 这是Android专用shebang千万别写成 #!/bin/sh 或 #!/usr/bin/env sh # 否则在大多数Android设备上会直接报错not found # 开头加一句日志方便后续确认是否执行 log -p i -t INIT_TEST Script started at $(date) # 设置一个系统属性这是最安全、最轻量的验证方式 # 不涉及文件读写、不依赖外部路径、不会因权限失败 setprop test.boot.ok 1 # 可选再写一条日志到dmesg内核日志双重确认 echo [INIT_TEST] boot script executed /dev/kmsg # 结束 exit 0为什么推荐用setprop而不是touch或echo /data/test.log因为setprop是系统级命令无需额外权限只要脚本本身能执行就一定能成功而写文件极易因/data未挂载、目录不存在、权限不足导致静默失败让你误以为脚本没跑。2.2 手动验证Push到手机立刻看效果在电脑端执行需已开启ADB调试# 将脚本推送到/system/bin/需要remount adb root adb remount 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 test.boot.ok # 应输出 1 # 查看日志 adb logcat -s INIT_TEST:I如果看到Script started at ...和test.boot.ok 1恭喜你的脚本已经通过第一关——它本身是合法、可执行、无副作用的。注意如果你的设备是user版本非userdebugadb remount可能失败。此时可临时用/data/local/tmp/替代/system/bin/测试后续开机阶段仍需放回/system或/vendor。3. 第二步让init认识它——在init.rc中声明服务3.1 找对位置别硬改/system/etc/init.rc直接修改init.rc风险高、易冲突且不同厂商路径差异大。更稳妥的做法是使用厂商预留的扩展入口。绝大多数Android设备高通、MTK、紫光展锐等都会在/system/etc/init/或/vendor/etc/init/下提供独立的.rc文件例如init.mtk.rcMTK平台init.qcom.rc高通平台init.vendor.rc通用vendor层你不需要自己找源码只需在设备上执行adb shell ls /system/etc/init/*.rc /vendor/etc/init/*.rc 2/dev/null找到一个存在且看起来“客户可定制”的文件比如init.vendor.rc。如果没有也可以新建一个init.test.rc放入/vendor/etc/init/需确保该目录在init启动时被include。3.2 写入服务定义在选定的.rc文件末尾添加以下内容# 开机脚本服务test_boot service test_boot /system/bin/init.test.sh class main user root group root oneshot seclabel u:object_r:test_service_exec:s0字段说明class main表示该服务属于main类会在init启动main类服务时被拉起时机早于late_start类oneshot执行完即退出不常驻适合初始化类脚本seclabel这是SELinux上下文声明先照抄下一步我们会配齐它保存后不需要重启整机。你可以用以下命令触发init重新加载配置Android 8.0支持adb shell stop adb shell start然后检查服务是否已注册adb shell getenforce # 确认SELinux是Enforcing还是Permissive adb shell ls -Z /system/bin/init.test.sh # 查看当前SELinux上下文应为u:object_r:shell_exec:s0待修正 adb shell getprop test.boot.ok # 此时应仍为空因为服务还没真正运行4. 第三步绕过SELinux拦路虎——最小化策略配置4.1 SELinux不是障碍而是开关很多教程把SELinux讲得神乎其技其实对开机脚本而言它就干一件事判断“谁”source能不能对“什么”target执行“哪种操作”action。我们的场景非常明确sourceinit进程类型是inittarget你的脚本文件我们将赋予它新类型test_service_execactionexecute执行所以只需两条规则告诉系统/system/bin/init.test.sh这个文件属于test_service_exec类型告诉系统init进程可以executetest_service_exec类型的文件4.2 实操三处文件改完即生效无需编译1声明文件类型file_contexts路径/vendor/etc/selinux/plat_file_contexts或/system/etc/selinux/plat_file_contexts优先查vendor在文件末尾添加一行/system/bin/init\.test\.sh u:object_r:test_service_exec:s0注意.需转义否则会被当通配符路径必须完全匹配。2定义类型与域test_service.te新建一个文件test_service.te内容仅需两行type test_service_exec, file_type, vendor_file_type; allow init test_service_exec:file { execute read open getattr };解释第一行定义新类型test_service_exec并声明它是file_type普通文件和vendor_file_type允许放在vendor分区第二行允许init进程对这类文件执行execute/read/open/getattr基本文件操作3加载策略关键免编译方案Android 8.0 支持运行时加载SELinux策略。将上面的test_service.te编译为二进制需checkpolicy工具但更简单的方法是直接用sepolicy-inject注入需设备已root或有adb shell root权限# 下载预编译的 sepolicy-injectGitHub可搜 adb push sepolicy-inject /data/local/tmp/ adb shell chmod 755 /data/local/tmp/sepolicy-inject # 注入规则一行命令搞定 adb shell /data/local/tmp/sepolicy-inject -s init -t test_service_exec -c file -p execute -l执行后立即生效无需重启。验证是否成功adb shell ls -Z /system/bin/init.test.sh # 应显示 u:object_r:test_service_exec:s0 adb shell dmesg | grep avc # 若无新avc denied日志说明策略已覆盖5. 第四步开机实测与排错指南5.1 终极验证重启看结果adb reboot # 等待设备完全启动后 adb wait-for-device adb shell getprop test.boot.ok # 应输出 1 adb logcat -s INIT_TEST:I | head -5 # 应看到启动日志如果一切正常你已经拥有了一个真正可用的开机脚本框架。5.2 常见问题速查表现象最可能原因快速解决getprop test.boot.ok无输出脚本根本没执行检查init.xxx.rc是否被正确include用adb shell psdmesg或logcat报avc: denied { execute }SELinux策略未生效重新执行sepolicy-inject确认file_contexts路径和正则正确检查ls -Z输出脚本执行但setprop失败init进程无set_prop权限在test_service.te中追加allow init property_socket:sock_file write;allow init self:process setpgid;极少需init.test.sh: not foundshebang错误或脚本损坏确认首行是#!/system/bin/sh用adb shell file /system/bin/init.test.sh检查是否为text文件避免Windows换行符提示所有修改.rc、file_contexts都可以通过adb push热更新无需刷机。策略注入也是运行时生效。这意味着你可以在10分钟内完成从编写到验证的完整闭环。6. 进阶建议让脚本更可靠、更实用6.1 加一层保险检测系统就绪状态有些操作如访问/data分区、调用am命令需等待zygote或surfaceflinger就绪。可在脚本开头加等待逻辑# 等待property服务就绪通常最早可用 while [ $(getprop sys.boot_completed) ! 1 ]; do sleep 1 done # 等待zygote启动可选 while [ $(getprop init.svc.zygote) ! running ]; do sleep 0.5 done6.2 日志集中管理统一打到logcat避免分散在dmesg/logcat//data/log/多个地方。全部走log命令log -p i -t MY_BOOT Step 1: Hardware init... log -p w -t MY_BOOT Warning: Sensor not ready log -p e -t MY_BOOT Error: Failed to load config6.3 安全边界限制脚本能力生产环境切勿在开机脚本中执行su、mount -o rw,remount等高危操作。如必须应使用runas切换到最小权限用户对输入参数做严格校验避免命令注入所有外部文件路径用绝对路径不依赖$PATH7. 总结你已掌握Android开机脚本的核心脉络回顾一下我们完成了什么写出一个零依赖、易验证的shell脚本用setprop规避权限陷阱在init.xxx.rc中正确定义服务明确class、user、oneshot语义用三行配置file_contextstest_service.tesepolicy-inject绕过SELinux全程免编译掌握开机实测与排错方法论不再被avc denied吓退获得一套可复用的工程化模板日志规范、等待机制、安全边界这不是一个“理论上可行”的Demo而是一个你明天就能用在项目中的最小可行方案。后续无论你要启动守护进程、预加载证书、还是初始化AI推理引擎底层机制都是一致的——只是脚本内容和SELinux策略细节不同而已。真正的Android系统定制往往就始于这样一个小小的init.test.sh。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。