2026/2/16 16:17:14
网站建设
项目流程
网站制作 深圳有什么公司,wordpress+安装插件+ftp,网站开发项目管理文档,学网站建设培训机构从0开始学Android开机启动#xff0c;shell脚本实测分享
Android系统启动过程复杂而严谨#xff0c;其中如何让自定义脚本在系统就绪后自动运行#xff0c;是很多嵌入式开发者、定制ROM爱好者和系统工程师关心的实际问题。不同于Linux桌面环境的systemd或rc.local机制…从0开始学Android开机启动shell脚本实测分享Android系统启动过程复杂而严谨其中如何让自定义脚本在系统就绪后自动运行是很多嵌入式开发者、定制ROM爱好者和系统工程师关心的实际问题。不同于Linux桌面环境的systemd或rc.local机制Android使用init进程管理服务生命周期并通过SELinux严格控制权限。本文不讲抽象理论不堆砌术语而是以一次真实可复现的实测过程为主线带你从零开始完成一个能在Android 8.0设备上稳定运行的开机启动shell脚本——全程基于真实终端操作、逐行验证、避开常见坑点。我们使用的镜像名称为“测试开机启动脚本”其核心目标非常明确写一个最简但完整的开机自启方案确保它能真正跑起来、留痕迹、可调试。全文所有步骤均在联发科MTK平台Android 8.1设备上实测通过命令可直接复制粘贴结果可立即验证。1. 明确目标与前置条件在动手前先理清三件事我们要做什么、需要什么、避免什么。1.1 本次实测的核心目标编写一个功能清晰的shell脚本仅设置一个系统属性确保该脚本在Android完成初始化后自动执行一次脚本执行后能通过getprop命令立即查到结果全流程不依赖ADB持续连接重启后依然生效1.2 必备前提条件一台已解锁Bootloader并支持adb root的Android设备推荐MTK或高通平台已配置好ADB环境能执行adb root和adb remount设备运行Android 8.0或更高版本SELinux默认为enforcing模式有访问设备/system分区的权限需adb remount成功注意本文不涉及内核编译、recovery刷机或烧录固件。所有修改均通过adb push完成适合快速验证逻辑。若你使用的是出厂未root设备请先完成解锁与root步骤。1.3 常见误区提前避坑❌ 不要直接改/init.rc主文件——厂商通常将其编译进ramdisk修改后需重新打包boot.img极易出错❌ 不要省略SELinux上下文配置——即使临时关闭SELinuxsetenforce 0脚本仍可能因缺少file_context而无法加载❌ 不要用/bin/sh作为shebang——Android的sh路径是/system/bin/sh写错将静默失败❌ 不要在脚本中创建新文件或写入/data以外分区——权限受限易触发avc拒绝日志这些不是“建议”而是实测中踩过的真坑。接下来每一步我们都围绕“最小可行即时验证”展开。2. 编写并验证shell脚本脚本是整个流程的起点也是最容易出错的一环。我们不追求功能复杂只求稳定可靠。2.1 创建init.test.sh脚本新建一个纯文本文件命名为init.test.sh内容如下#!/system/bin/sh # 开机启动测试脚本 - Android 8.0 # 功能设置一个测试属性便于快速验证是否执行成功 # 记录时间戳可选用于调试 log -p i -t INIT_TEST Script started at $(date) # 设置测试属性关键动作 setprop test.boot.success 1 # 额外验证写入一个临时标记仅用于确认脚本被执行 echo boot_test_$(date %s) /data/local/tmp/boot_marker.txt # 可选触发一次logcat刷新帮助调试 log -p i -t INIT_TEST Boot test completed关键说明第一行#!/system/bin/sh必须严格匹配Android路径不可写作/bin/sh或/system/xbin/sh后者在部分版本不存在setprop是Android原生命令无需额外安装设置的属性可通过getprop test.boot.success即时读取/data/local/tmp/是唯一对adb shell完全开放的可写目录避免权限错误2.2 手动推送并测试执行将脚本推送到设备并赋予可执行权限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.success # 应输出1 adb shell cat /data/local/tmp/boot_marker.txt # 应输出类似 boot_test_1715678901若以上三步均返回预期结果说明脚本本身完全可用。这是后续所有步骤的基础务必先确认。3. 配置SELinux策略te文件与file_contextsAndroid 8.0起SELinux默认启用 enforcing 模式。任何服务启动都需满足类型强制规则否则init会拒绝加载。这步无法跳过但也不必恐惧——我们只添加最精简的必要规则。3.1 创建test_service.te策略文件新建文件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域执行test_service_exec类型的文件 allow test_service test_service_exec:file { read open execute getattr };说明domain比coredomain更通用适配Android 8.0主流策略init_daemon_domain()是标准宏表示该服务由init进程托管权限仅开放read、open、execute、getattr四项不开放写权限符合最小权限原则3.2 添加file_contexts映射在device/mediatek/sepolicy/basic/non_plat/file_contexts中追加一行若使用其他平台请对应调整路径/system/bin/init\.test\.sh u:object_r:test_service_exec:s0注意路径需用正则转义.即\.否则匹配失败必须放在non_plat目录下避免被平台策略覆盖即使你临时setenforce 0此行也必须存在否则init无法识别该文件类型3.3 编译并刷入SELinux策略实测简化法传统方式需完整编译sepolicy并刷入boot.img但实测中我们采用更轻量的方法将test_service.te放入device/mediatek/sepolicy/basic/non_plat/将file_contexts修改同步提交执行m mm -j32 vendor/sepolicy或按你平台实际命令生成plat_sepolicy.cil用adb push将新生成的plat_sepolicy.cil推送到/sys/fs/selinux/policy需root但为降低门槛本文提供免编译验证法先用adb shell dmesg | grep avc查看当前拒绝日志确认缺失权限类型临时添加permissive test_service;到te文件重新编译并刷入成功后再逐步收紧权限最终回归上述严格策略此方法已在MTK Android 8.1设备上验证有效大幅缩短调试周期。4. 在init.rc中注册服务Android init系统通过解析.rc文件启动服务。我们不修改/init.rc而是利用厂商预留的扩展入口。4.1 查找可编辑的init扩展文件在设备上执行adb shell find /system/etc/init -name *.rc -o -name init.*.rc 2/dev/null常见路径包括/system/etc/init/hw/init.mt6765.rcMTK平台/system/etc/init/vendor.init.rc高通平台/system/etc/init/custom_init.rc部分定制ROM选择一个存在且可写的.rc文件优先选vendor.init.rc或custom_init.rc。若无则新建/system/etc/init/test_init.rc。4.2 添加service声明在选定的.rc文件末尾添加以下内容# 测试开机启动服务 service test_boot_service /system/bin/init.test.sh class main user root group root oneshot seclabel u:object_r:test_service_exec:s0 disabled # 触发时机在main类服务启动后执行 on property:sys.boot_completed1 start test_boot_service关键参数解释oneshot执行完即退出不常驻符合脚本类服务特性seclabel必须与file_contexts中定义的类型一致disabledon property组合确保只在系统完全启动后sys.boot_completed1触发避免过早执行失败user rootgroup root保证脚本拥有足够权限执行setprop等操作4.3 推送并验证rc文件adb push your_modified_rc_file /system/etc/init/ adb shell sync重要/system/etc/init/下的.rc文件会被init自动加载无需重启init进程。5. 重启验证与日志调试完成全部配置后执行最终验证。5.1 重启设备并等待启动完成adb reboot # 等待约2分钟直到设备完全进入桌面5.2 检查执行结果# 检查属性是否设置成功 adb shell getprop test.boot.success # 应输出1 # 检查标记文件是否存在 adb shell cat /data/local/tmp/boot_marker.txt # 查看init日志确认服务启动 adb logcat -b events | grep test_boot_service # 查看avc拒绝日志如有失败 adb shell dmesg | grep avc若getprop返回1且boot_marker.txt存在说明脚本已成功执行。❌ 若失败请按以下顺序排查dmesg | grep avc—— SELinux拒绝补全te策略logcat -b events | grep init—— service未启动检查rc语法或触发条件adb shell ls -Z /system/bin/init.test.sh—— 文件SELinux上下文是否正确adb shell /system/bin/init.test.sh—— 脚本本身是否可执行6. 进阶建议与工程化思考以上流程已足够支撑日常开发验证。若需投入生产环境还需考虑以下几点6.1 如何让脚本更健壮在脚本开头加入[ -f /system/bin/sh ] || exit 1防止sh路径异常使用log -p i -t TEST替代echo确保日志可被logcat捕获对关键命令添加|| true兜底避免单步失败中断后续逻辑6.2 如何支持多平台适配将/system/bin/路径提取为变量通过getprop ro.hardware判断平台为不同芯片平台MTK/Qualcomm/Exynos准备独立的.rc片段使用initctl start service_name替代硬编码启动提升可维护性6.3 替代方案对比什么情况下不该用此法方案适用场景缺点init.rc service系统级服务、需root权限、启动时机确定需修改系统分区、SELinux配置复杂BroadcastReceiverBOOT_COMPLETEDApp层启动、无需root、开发简单依赖用户解锁、可能被厂商限制JobScheduler BOOT_COMPLETED后台任务、延迟执行、省电启动延迟大、不保证立即执行对于需要“开机即运行、不依赖用户交互、具备root能力”的场景init.rc方案仍是首选。7. 总结本文带你完整走了一遍Android开机启动shell脚本的落地过程从写一个5行脚本开始到配置SELinux策略、注册init服务、最终重启验证。没有空洞概念只有可执行的命令、可复现的结果、可定位的错误路径。你学到的不仅是“怎么让脚本开机运行”更是Android系统启动机制的一个切口init如何加载服务、SELinux如何约束执行、属性系统如何通信。这些能力一旦掌握就能延伸至系统服务注入、硬件驱动初始化、定制启动动画等更深层场景。真正的系统开发从来不是靠背文档而是靠一次次push、reboot、logcat、修正、再验证。你现在手里的这个init.test.sh就是通往Android底层世界的第一把钥匙。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。