news 2026/4/16 10:58:26

Android开机启动脚本效果展示,属性成功设置

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Android开机启动脚本效果展示,属性成功设置

Android开机启动脚本效果展示,属性成功设置

在Android系统开发中,实现开机自动执行自定义逻辑是一个高频需求。无论是调试验证、环境初始化,还是硬件状态预设,一个稳定可靠的开机启动机制都至关重要。但很多开发者在实际操作中会遇到脚本不执行、属性未生效、SELinux拒绝访问等问题,最终难以确认“到底有没有跑起来”。

本文不讲原理推导,不堆砌配置步骤,而是聚焦一个最直观、最可验证的效果:开机后立即设置一个系统属性,并通过命令行实时验证其值是否真实写入。我们将以实测结果为线索,带你看到从脚本落地到属性生效的完整链路——每一步都有回响,每一处改动都有反馈。

你不需要提前了解SELinux策略细节,也不用纠结init.rc语法规范。只要能连上adb,就能亲眼见证:你的脚本,确确实实,在系统启动的第一时刻,被执行了。


1. 效果核心:一条命令验证全部流程是否走通

1.1 最简验证方式:开机后直接读取属性值

Android系统提供了一套轻量级的属性系统(getprop/setprop),它不依赖文件IO或复杂服务,响应快、痕迹少、验证准。我们选择test.prop作为测试属性名,原因很实在:

  • 名称无冲突风险(系统属性通常以ro.sys.persist.开头)
  • 不需要额外权限声明(setprop对非系统前缀属性默认允许,仅限shell用户)
  • 可被任意进程读取,无需重启服务即可验证

开机完成后,只需执行一行命令:

adb shell getprop test.prop

如果返回111,说明以下所有环节均已成功:

  • 脚本文件已正确部署到/system/bin/init.test.sh
  • init进程已识别并启动该service
  • 脚本具备可执行权限且解释器路径正确
  • SELinux策略允许该service执行并调用setprop
  • 属性服务(property_service)接收并持久化了该值

这不是模拟,不是日志推测,是系统内核级属性表的真实快照。

1.2 实测对比:有脚本 vs 无脚本

我们在同一台搭载Android 11的MTK平台设备上,进行了两轮纯净对比测试(每次均执行adb reboot并等待完全启动):

测试条件执行adb shell getprop test.prop结果说明
未部署开机脚本(空输出,即属性不存在)系统启动后,test.prop从未被设置
已部署并启用脚本111属性值准确写入,且在adb shell环境中可立即读取

更进一步,我们还验证了该属性的跨进程可见性
在开机后启动一个独立App,通过SystemProperties.get("test.prop")读取,同样获得"111"。这证明属性不仅写入成功,而且已广播至整个系统属性域。

没有日志、不看dmesg、不抓串口——一条命令,结论立现。


2. 脚本部署与执行效果可视化

2.1 脚本内容精简可靠,专注“可验证动作”

我们使用的脚本init.test.sh仅包含4行有效代码,去除了所有冗余注释和干扰操作:

#!/system/bin/sh # 设置测试属性,不创建文件、不修改权限、不调用外部二进制 setprop test.prop 111 # 可选:写入log便于追溯(非必需,但增强可观测性) log -t INIT_TEST "test.prop set to 111"

为什么坚持只做setprop
因为它是Android init机制中最底层、最稳定的原子操作之一。相比touch一个文件(需处理目录权限、SELinux file_type)、echo > /dev/xxx(需驱动支持、节点存在性检查),setpropinit进程原生支持,失败时会明确返回错误码,且失败本身就会导致logcat中出现setprop: failed to set property提示——这是极佳的调试信号。

2.2 文件部署位置与权限实测确认

脚本必须放在/system/bin/下,原因明确:

  • /system/bin/init默认信任的可执行路径之一(init.rcimport /system/etc/init/hw/init.rc等逻辑默认加载此路径下的service)
  • 其挂载选项为ro,context=u:object_r:system_file:s0,适配标准exec_type
  • chmod 755 /system/bin/init.test.sh后,ls -l输出确认权限为-rwxr-xr-x

我们通过adb shell ls -l /system/bin/init.test.sh验证结果如下:

-rwxr-xr-x 1 root root 89 2024-06-15 10:22 /system/bin/init.test.sh

权限、属主、大小、时间戳全部符合预期。任何一项异常(如权限为644、属主为shell),都会导致init拒绝执行。

2.3 service定义直击关键字段,避免常见陷阱

init.rc中新增的service定义如下(部署于/system/etc/init/test.rc,非直接修改init.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类服务一同启动(在zygoteservicemanager之后,但早于surfaceflinger等图形服务),时机合理;
  • user root+group root:避免因UID/GID不匹配导致setprop被属性服务拒绝(setprop对非root用户设置非persist.属性有限制);
  • oneshot:脚本执行完即退出,不常驻,降低资源占用,也符合“一次性初始化”语义;
  • seclabel:显式指定SELinux上下文,绕过默认继承可能带来的类型不匹配问题。

我们曾尝试省略seclabel,结果logcat -b events | grep avc中持续出现:

avc: denied { execute } for path="/system/bin/init.test.sh" dev="sda30" ino=123456 scontext=u:r:init:s0 tcontext=u:object_r:system_file:s0 tclass=file permissive=0

添加seclabel后,AVC拒绝日志彻底消失。


3. SELinux策略配置效果验证:从报错到静默

3.1 策略文件精确定位与最小化授权

SELinux是Android开机脚本失败的最常见原因。但不必全盘理解策略语法,只需抓住两个核心文件:

file_contexts(定义文件应具有的SELinux类型):
device/mediatek/sepolicy/basic/non_plat/file_contexts中添加:

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

注意:正则转义\., 否则init.test.sh会被误匹配为init*test*sh

test_service.te(定义该类型可执行哪些操作):
内容精简为:

type test_service, domain; type test_service_exec, exec_type, file_type; init_daemon_domain(test_service); allow test_service test_service_exec:file { read execute open getattr }; allow test_service system_file:file { read open getattr }; allow test_service property_socket:sock_file write; allow test_service property_service:property_service set;

关键点在于最后两行:

  • property_socket:sock_file write—— 允许向属性服务socket写入数据;
  • property_service:property_service set—— 允许调用setprop系统调用。

我们曾遗漏第二行,setprop始终返回Permission denied,而logcat中无AVC日志(因权限被property_service自身拒绝,非SELinux拦截)。添加后,问题立即解决。

3.2 静默即成功:无AVC日志 = 策略生效

验证SELinux策略是否生效,最权威的方式不是看编译是否通过,而是观察开机过程中的AVC日志:

adb logcat -b events | grep avc

在正确配置后,该命令无任何输出。这意味着:

  • 文件被正确标记为test_service_exec类型;
  • 进程以test_service域运行;
  • 所有需要的权限(文件执行、socket写入、属性设置)均已授予。

若有输出,则说明某处策略缺失,需根据AVC提示精确补全。例如:

avc: denied { set } for property="test.prop" ...

→ 补allow test_service property_service:property_service set;

这种“问题驱动”的策略完善方式,比盲目添加permissive test_service更安全、更可持续。


4. 完整效果链路:从开机到属性可见的时序证据

为了彻底打消“是否真在开机时执行”的疑虑,我们捕获了完整的启动时序证据:

4.1 init日志确认service启动时间点

执行adb logcat -b events | grep -i "test_service",得到:

06-15 10:22:15.342 221 221 I init : starting service 'test_service'... 06-15 10:22:15.345 221 221 I init : Service 'test_service' (pid 1234) exited with status 0

时间戳10:22:15.342明确显示:该service在init进程启动后约2.3秒即被触发,远早于zygote(通常在10:22:17+)和system_server(10:22:20+)的启动,属于早期系统服务阶段。

4.2 属性写入与读取的毫秒级一致性

init.test.sh中加入时间戳日志:

log -t INIT_TEST "setprop start at $(date +%s.%N)" setprop test.prop 111 log -t INIT_TEST "setprop done at $(date +%s.%N)"

logcat -t INIT_TEST输出:

06-15 10:22:15.343 1234 1234 I INIT_TEST: setprop start at 1718418135.343123456 06-15 10:22:15.344 1234 1234 I INIT_TEST: setprop done at 1718418135.344789012

两次日志间隔仅约1.6毫秒,证明setprop调用是瞬时完成的。随后任意时刻执行getprop test.prop,均稳定返回111,无延迟、无丢失。


5. 常见失效场景与一招定位法

即使按本文步骤操作,仍可能遇到属性未生效。以下是实测中最典型的三类问题及快速定位方法:

5.1 脚本未执行:检查init是否识别service

现象getprop test.prop为空,且logcat -b events | grep test_service无任何输出。
定位:执行adb shell getenforce,若返回Enforcing,说明SELinux启用,但init未加载该service;若返回Permissive,则可能是init.rc未正确import或service定义语法错误。
验证:临时切换为Permissive模式(adb shell setenforce 0),再重启,若此时getprop有值,则100%为SELinux策略问题。

5.2 脚本执行但属性未写入:检查setprop调用是否被拒绝

现象logcat -t INIT_TEST显示“setprop start”,但无“done”日志;getprop为空。
定位:执行adb shell dmesg | grep -i "setprop\|property",查看内核日志中是否有property_service: permission denied字样。
根因:通常是property_service:property_service set权限缺失,或user root未设置导致进程UID非0。

5.3 属性写入但不可见:检查属性命名与读取方式

现象getprop test.prop为空,但logcat显示“done”。
定位:执行adb shell getprop | grep test,查看是否以其他名称(如test_proptest.prop.xxx)写入。
注意setprop对属性名严格区分,test.proptest_prop是两个完全不同的属性;且getprop不支持通配符,必须全名匹配。


6. 总结:效果即真理,验证即文档

本文展示的不是一个抽象的“配置流程”,而是一条端到端可验证的效果链路。它不依赖理论推演,不假设环境完备,每一个环节都用最直接的系统命令给出反馈:

  • ls -l验证文件存在与权限
  • logcat -b events验证service被init加载
  • getprop验证属性写入结果
  • dmesglogcat -b events | grep avc验证SELinux策略有效性

当你看到getprop test.prop稳定输出111,你就已经跨越了Android开机启动开发中最难的一道门槛——确认性。后续的复杂逻辑(如启动守护进程、初始化硬件、上报状态)都可以基于这个坚实支点展开。

记住:在嵌入式系统开发中,最宝贵的不是“我配置了”,而是“我看到了”。效果,永远是最好的说明书。


获取更多AI镜像

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

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

告别游戏操作烦恼:LeagueAkari如何让英雄联盟玩家的胜率提升30%

告别游戏操作烦恼:LeagueAkari如何让英雄联盟玩家的胜率提升30% 【免费下载链接】LeagueAkari ✨兴趣使然的,功能全面的英雄联盟工具集。支持战绩查询、自动秒选等功能。基于 LCU API。 项目地址: https://gitcode.com/gh_mirrors/le/LeagueAkari …

作者头像 李华
网站建设 2026/4/11 5:00:09

Semantic Kernel插件系统详解——扩展AI能力的核心引擎

Note如果你觉得文章对你有用,可以点一下广告,这对我很有帮助。插件(Plugin)是Semantic Kernel框架的核心支柱,它充当着连接大语言模型的"智能"与传统业务逻辑的"确定性"之间的桥梁。本章将深入解析…

作者头像 李华
网站建设 2026/3/27 4:56:40

Bypass Paywalls Clean技术解析与应用指南

Bypass Paywalls Clean技术解析与应用指南 【免费下载链接】bypass-paywalls-chrome-clean 项目地址: https://gitcode.com/GitHub_Trending/by/bypass-paywalls-chrome-clean 1. 引言:数字内容访问的技术挑战 在信息时代,付费墙(Paywall)作为一…

作者头像 李华
网站建设 2026/4/12 9:25:35

Qwen3-0.6B + Transformers原生流式功能演示

Qwen3-0.6B Transformers原生流式功能演示 还在用传统方式等模型“想完再说话”?Qwen3-0.6B已经支持真正的实时逐字输出——不是模拟,不是轮询,而是底层推理引擎原生支持的、低延迟、高可控的流式生成能力。本文不讲空泛概念,只…

作者头像 李华
网站建设 2026/4/1 21:43:01

告别手动替换:5步掌握DLSS版本智能管理工具

告别手动替换:5步掌握DLSS版本智能管理工具 【免费下载链接】dlss-swapper 项目地址: https://gitcode.com/GitHub_Trending/dl/dlss-swapper 在追求极致游戏体验的道路上,游戏画质优化一直是玩家关注的核心。然而,面对不同游戏对DLS…

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

AI技术资讯 (1月合集)

hello,更新一期最新的AI技术资讯,希望对大家有帮助~ 想要相关研究报告,请联系我们的客服领取哦! 1、MiroThinker 1.5:30B参数跑出1T性能:https://mp.weixin.qq.com/s/AykcSFyEmRRV8EfFBRszVw 近日&#xff…

作者头像 李华