news 2026/2/11 14:35:03

简单易懂!Android开机启动shell脚本新手入门教程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
简单易懂!Android开机启动shell脚本新手入门教程

简单易懂!Android开机启动shell脚本新手入门教程

你是不是也遇到过这样的问题:想让Android设备一开机就自动执行某个任务,比如备份日志、初始化硬件、启动监控服务,或者调试时快速设置系统属性?但一看到“init.rc”“SELinux”“te文件”这些词就头大?别担心——这篇教程就是为你写的。

它不讲晦涩的底层原理,不堆砌术语,不假设你已经熟悉AOSP编译或SELinux策略编写。我们只聚焦一件事:用最直接的方式,让你在真实设备上跑通一个开机就能执行的shell脚本。哪怕你是第一次接触Android系统定制,只要会写几行shell、能用adb推文件、知道怎么重启手机,就能跟着做完。

全文没有“赋能”“生态”“深度集成”这类空话,只有可验证的步骤、可复制的代码、可复现的结果。每一步都标注了“为什么这么做”,哪里容易出错、怎么快速验证、报错了怎么看日志——全是工程师踩坑后总结的实操经验。

准备好了吗?我们从零开始。

1. 先搞清楚:你的目标到底是什么

在动手前,请确认你真正需要的是什么:

  • 开机后自动运行一段命令(比如setprop debug.test 1logcat -f /data/log/boot.log
  • 不需要图形界面,纯后台执行
  • 脚本只需执行一次(oneshot)或常驻(daemon),不涉及复杂服务管理
  • 你有root权限的测试机(或可刷自定义system镜像的开发板)
  • ❌ 不是想做App级自启(那该用BroadcastReceiver)
  • ❌ 不是想绕过厂商锁刷ROM(本教程不涉及解锁Bootloader)
  • ❌ 不是想在用户空间App启动时触发(那是Framework层的事)

如果你的需求符合上面前三条,那就继续往下看。我们不追求“完美适配所有芯片平台”,而是先确保在主流Android 8.0+设备(如MTK/高通公版)上稳定跑通,再谈扩展。

2. 最小可行方案:三步走通开机脚本

很多教程一上来就让你改init.rc、写te策略、编译整个系统——这完全没必要。对于验证逻辑、快速调试、内部测试来说,我们可以用更轻量的方式实现目标。整个流程就三步:

  1. 写一个极简shell脚本,并手动验证它能在设备上运行
  2. 把脚本放进系统可执行路径,并赋予正确权限
  3. init.rc中添加一条service声明,指定开机启动

后面两步(SELinux策略、te文件)我们放在“进阶排错”里讲——因为很多测试场景下,临时关闭SELinux或使用已有domain就能跳过它们。先让脚本能跑起来,比纠结策略文件更有价值。

2.1 写一个真正能用的shell脚本

新建一个文件,命名为init.test.sh,内容如下:

#!/system/bin/sh # 开机脚本标准开头:必须用/system/bin/sh,不是/bin/sh # Android的sh路径和Linux不同,写错直接静默失败 # 第一步:记录脚本已运行(方便验证是否真被调用) log -p i -t "boot_script" "init.test.sh started at $(date)" # 第二步:设置一个系统属性(最安全的测试动作,无副作用) setprop sys.boot.test 1 # 第三步:写入一行日志到/data(需确保/data可写) echo "Boot script executed on $(date)" > /data/boot_log.txt # 可选:如果需要持续运行(如监听事件),取消下面注释 # while true; do # log -p i -t "boot_script" "still alive..." # sleep 30 # done

关键注意点:

  • 第一行#!/system/bin/sh必须严格匹配,不能写成#!/bin/sh或漏掉/system
  • 所有命令路径要写全(如/system/bin/log而非log),避免PATH环境变量不可靠
  • 避免创建新文件到/system分区(只读),优先用/data/dev等可写路径
  • log命令是Android专用日志工具,比echo更能被logcat捕获

验证方法(非常重要!):
用adb把脚本推到手机并手动执行一次:

adb push init.test.sh /data/local/tmp/ adb shell chmod +x /data/local/tmp/init.test.sh adb shell /data/local/tmp/init.test.sh adb logcat -t 10 -s boot_script

如果看到"init.test.sh started at..."日志,且/data/boot_log.txt文件生成成功,说明脚本本身完全没问题。

2.2 把脚本放进系统路径并设好权限

Android开机时,init进程只信任特定路径下的可执行文件。最稳妥的位置是/system/bin/(需remount system为可写):

# 1. remount system分区为可写(需要root) adb root adb remount # 2. 推送脚本到/system/bin/ adb push init.test.sh /system/bin/init.test.sh # 3. 设置权限:所有者可读可写可执行,其他用户仅可执行 adb shell chmod 755 /system/bin/init.test.sh # 4. 验证权限是否正确 adb shell ls -l /system/bin/init.test.sh # 应输出:-rwxr-xr-x root root ... /system/bin/init.test.sh

小技巧:如果你不想每次刷机都手动推,可以把这一步写成一个adb一键脚本,后续反复测试非常省时。

2.3 在init.rc中添加service声明

现在脚本已就位,下一步是告诉Android的init进程:“这个脚本,开机时请帮我跑一次”。

大多数设备不会让你直接修改/system/etc/init.rc(它是编译生成的),但几乎都支持加载额外的.rc文件。常见位置包括:

  • /system/etc/init/(Android 8.0+ 推荐方式,支持.rc文件自动加载)
  • /system/etc/init/hw/init.<vendor>.rc(厂商自定义rc文件)
  • /vendor/etc/init/(vendor分区,部分设备支持)

我们采用最通用的方式:在/system/etc/init/下新建一个test_boot.rc文件:

# /system/etc/init/test_boot.rc service test_boot /system/bin/init.test.sh class main user root group root oneshot seclabel u:object_r:shell_exec:s0

各字段含义:

  • service test_boot:服务名,任意取,但不能和已有服务重名
  • /system/bin/init.test.sh:脚本绝对路径
  • class main:属于main类,会在zygote启动前运行
  • user/group root:以root身份运行(必要,否则无法设置系统属性)
  • oneshot:执行完即退出(适合初始化类脚本);若需常驻,改为disabled并在其他trigger中启用
  • seclabel u:object_r:shell_exec:s0:复用系统已有的shell_execSELinux域(关键!避免立即写te文件)

推送并验证rc文件:

adb push test_boot.rc /system/etc/init/test_boot.rc adb shell chmod 644 /system/etc/init/test_boot.rc adb reboot

重启后,等待约30秒,执行:

adb logcat -b events -t 20 | grep -i test adb logcat -t 20 -s boot_script adb shell cat /data/boot_log.txt

如果三处都看到预期输出,恭喜你——开机启动脚本已成功运行

3. 常见问题与快速排错指南

即使按上述步骤操作,也可能遇到“脚本没执行”“报Permission denied”“logcat看不到日志”等问题。别急,90%的问题都集中在以下四个环节,我们逐个击破:

3.1 脚本根本没被init调用?检查rc文件加载状态

init进程启动时会打印加载了哪些rc文件。用以下命令确认你的test_boot.rc是否被识别:

adb logcat -b events | grep -i "import\|parse" # 正常应看到类似:import /system/etc/init/test_boot.rc

如果没看到,说明rc文件路径错误或格式非法。检查:

  • 文件是否在/system/etc/init/目录下(不是子目录)
  • 文件名必须以.rc结尾
  • rc文件内容不能有Windows换行符(\r\n),用dos2unix转换
  • 每行末尾不能有多余空格

3.2 脚本执行了但报错?看init日志定位

init进程的错误不会出现在普通logcat里,要用-b events缓冲区:

adb logcat -b events | grep -i "test_boot\|init.test" # 查看是否有 service_start_failed、permission denied 等关键词

典型错误及解法:

  • Failed to open '/system/bin/init.test.sh'→ 路径写错,或文件不存在(检查adb shell ls /system/bin/init.test.sh
  • Cannot execv('/system/bin/init.test.sh')→ 权限不对(chmod 755再试)或shebang路径错误(确认是/system/bin/sh
  • Permission denied→ SELinux拒绝(见3.3节)
  • Invalid argument→ rc文件语法错误(如多了一个空格、少了一个换行)

3.3 SELinux报错怎么办?两种务实解法

当你在logcat中看到类似avc: denied { execute } for path=/system/bin/init.test.sh的日志,说明SELinux策略阻止了执行。

别急着写te文件——先试试这两个更快的方案:

方案A:临时切换SELinux为permissive模式(仅测试用)
adb shell setenforce 0 adb reboot

重启后如果脚本正常运行,证明确实是SELinux拦截。这是最快速的验证手段。

方案B:复用现有SELinux域(推荐长期使用)

在rc文件中,把seclabel行改成:

seclabel u:object_r:shell_exec:s0

shell_exec是系统预置的、允许执行shell脚本的domain,绝大多数设备都开放了对它的execute权限。只要你的脚本不访问敏感资源(如/dev/block/sys/fs/selinux),这个配置足够安全且无需额外策略。

注意:不要用u:r:init:s0u:r:kernel:s0等高权限domain,存在安全风险。

3.4 日志看不到?换个缓冲区或加调试输出

Android logcat默认只显示mainsystemradio缓冲区。开机早期的日志在eventskernel缓冲区:

# 查看init相关事件 adb logcat -b events # 查看内核级日志(含SELinux avc) adb logcat -b kernel | grep -i avc # 强制脚本输出到多个地方(增强可观测性) echo "[$(date)] Script running" >> /data/local/tmp/boot_debug.log log -p i -t "boot_debug" "Script running"

4. 进阶技巧:让脚本更可靠、更实用

当基础流程跑通后,你可以根据实际需求升级脚本能力。以下是几个高频、低风险、高价值的增强点:

4.1 判断是否首次启动,避免重复执行

有些操作(如初始化数据库、生成密钥)只需做一次。用getprop检查标记:

#!/system/bin/sh if [ "$(getprop sys.boot.test.done)" != "1" ]; then log -p i -t "boot_script" "First boot: doing init tasks..." # 这里放你的初始化命令 setprop sys.boot.test.done 1 else log -p i -t "boot_script" "Not first boot, skip init" fi

4.2 等待关键服务就绪后再执行

init.rc中某些service依赖其他服务(如surfaceflingermedia)。用wait_for_prop确保时机:

service test_boot /system/bin/init.test.sh class main user root group root oneshot seclabel u:object_r:shell_exec:s0 # 等待zygote启动完成(表示Framework已就绪) wait_for_prop sys.boot_completed 1

4.3 支持热更新:脚本内容可远程替换

把核心逻辑抽离到/data分区(可读写),主脚本只负责加载:

#!/system/bin/sh # 主脚本只做一件事:执行/data下的真实逻辑 if [ -f /data/local/tmp/real_boot.sh ]; then /data/local/tmp/real_boot.sh fi

这样你无需每次改脚本都重启,adb push新版本到/data即可生效。

5. 总结:你已经掌握的核心能力

回顾一下,你现在完全可以独立完成以下事情:

  • 编写一个符合Android规范的开机shell脚本,并手动验证其功能
  • 将脚本部署到/system/bin/并设置正确权限
  • 通过/system/etc/init/xxx.rc方式注册开机service,无需修改主init.rc
  • 快速定位并解决“脚本不执行”“Permission denied”“日志看不到”等典型问题
  • 在不写te文件的前提下,利用shell_execdomain绕过SELinux限制
  • 为脚本增加首次启动判断、服务等待、热更新等实用特性

这些能力足以支撑你完成绝大多数Android系统级自动化任务:日志自动归档、硬件自检、调试开关预置、OTA前数据备份、工厂模式快捷入口等。

记住,系统定制不是玄学。它是一系列可验证、可调试、可回滚的操作。每一次成功的开机脚本,都是你对Android启动流程理解更深一步的证明。


获取更多AI镜像

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

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

Keil代码提示设置全攻略:IDE配置深度剖析

以下是对您提供的博文《Keil代码提示设置全攻略&#xff1a;IDE配置深度剖析》的 专业级润色与重构版本 。本次优化严格遵循您的全部要求&#xff1a; ✅ 彻底去除AI痕迹&#xff0c;语言自然、老练、有“人味”——像一位十年嵌入式老兵在技术分享会上娓娓道来&#xff1b;…

作者头像 李华
网站建设 2026/2/11 10:08:06

DeepSeek-Coder vs IQuest-Coder-V1:长文本处理能力对比评测

DeepSeek-Coder vs IQuest-Coder-V1&#xff1a;长文本处理能力对比评测 1. 为什么长文本能力对程序员真正重要&#xff1f; 你有没有遇到过这些情况&#xff1f; 看一个开源项目的 README 和核心模块代码&#xff0c;想快速理解整体架构&#xff0c;但模型一看到几千行就“…

作者头像 李华
网站建设 2026/2/4 8:31:05

一键部署Unsloth环境,快速开启LLM微调之旅

一键部署Unsloth环境&#xff0c;快速开启LLM微调之旅 你是否曾为大模型微调卡在环境配置上几个小时&#xff1f;显存不够、CUDA版本不匹配、依赖冲突、安装报错……这些痛点让很多想动手实践的朋友望而却步。今天&#xff0c;我们不讲理论&#xff0c;不堆参数&#xff0c;直…

作者头像 李华
网站建设 2026/2/7 3:36:52

SGLang企业应用案例:智能客服系统高吞吐部署实战

SGLang企业应用案例&#xff1a;智能客服系统高吞吐部署实战 1. 为什么智能客服需要SGLang&#xff1f; 你有没有遇到过这样的场景&#xff1a;电商大促期间&#xff0c;客服系统突然涌入上万并发咨询&#xff0c;响应延迟飙升到5秒以上&#xff0c;用户反复刷新、投诉激增&a…

作者头像 李华
网站建设 2026/2/5 4:29:52

cv_resnet18_ocr-detection效果惊艳!办公文档自动化处理新方式

cv_resnet18_ocr-detection效果惊艳&#xff01;办公文档自动化处理新方式 OCR技术早已不是新鲜概念&#xff0c;但真正能在日常办公中“开箱即用、一用就灵”的工具却不多。最近试用了一款由科哥构建的轻量级OCR文字检测模型——cv_resnet18_ocr-detection&#xff0c;部署后…

作者头像 李华
网站建设 2026/2/11 14:27:23

Unsloth推理延迟优化:生成速度提升实战技巧

Unsloth推理延迟优化&#xff1a;生成速度提升实战技巧 1. Unsloth 是什么&#xff1f;不只是快一点&#xff0c;而是重新定义效率 你有没有试过等一个模型生成回复&#xff0c;手指不自觉地敲着桌面&#xff0c;心里默数“三、二、一……怎么还没好”&#xff1f;这不是你的…

作者头像 李华