10分钟装出第一个Magisk模块:从module.prop到打包刷入的完整教程
10分钟装出第一个Magisk模块从module.prop到打包刷入的完整教程【免费下载链接】MagiskThe Magic Mask for Android项目地址: https://gitcode.com/GitHub_Trending/ma/Magisk想在 Android 设备里加个tree命令或者把系统某个属性改掉可没人愿意为了这一个功能去重刷 ROM 或者重新编译镜像。Magisk模块开发干的就是这件事把你要改动的文件打包成一个标准结构的小模块刷进设备后由 Magisk 在开机时无感地合并进系统分区——系统文件本身一个字节都没动。这篇教程走一遍完整闭环先花十分钟装出你的第一个模块再拆开讲清楚挂载机制和脚本时机最后把新手最常踩的 5 个坑摆出来对号入座。快速上手10分钟刷进第一个Magisk模块先别抠原理跟着做一遍再说。你只需要一个能正常刷模块的 Magisk 环境App 主页能看到 Installed 版本即已装好和电脑上任意一个压缩工具。模块就是一个文件夹最小可运行结构长这样my_tool/ ├── module.prop # 模块元数据必需 └── system/ └── bin/ └── tree # 你要注入/替换的文件按系统路径摆放system/里的一切都会按相对路径合并进真实的/system所以把tree二进制丢进system/bin/后重启就能直接在终端里敲tree。module.prop 字段速查module.prop格式是严格规定的一行一个键值对必须用 UNIXLF换行符idmy_tool name我的第一个工具模块 version1.0 versionCode1 authoryou description向/system/bin注入tree命令其中id必须匹配正则^[a-zA-Z][a-zA-Z0-9._-]$——字母开头只含字母、数字、.、_、-。versionCode必须是整数App 靠它比较版本新旧。打包成 ZIP 的正确姿势模块打包最容易出的问题就是目录层级。记住ZIP 的最外层就是 module.prop 和 system 目录不要再套一层文件夹。把my_tool文件夹里的内容不是文件夹本身压缩成my_tool.zip然后丢进 Magisk App 的模块页刷入。刷完后在 root 终端里验证一下magisk --list-modules输出里出现my_tool且tree能跑第一个模块就成了。剩下没展开的细节标记文件、挂载原理、调试手段下一节逐个拆。拆开一个模块看看文件清单与触发时机刷完模块去/data/adb/modules/你的id/里翻一圈会发现里面比你预想的多。用一张表把常见成员的作用和触发时机全部说清文件/目录是否必需作用何时生效module.prop必需元数据id、名称、版本、作者App 识别模块的依据安装后常驻system/建议保留要被合并进真实/system的文件含vendor/、product/、system_ext/子路径每次开机挂载阶段post-fs-data.sh可选早期启动脚本/data解密挂载后、模块挂载之前阻塞启动最多等 40 秒service.sh可选后期服务脚本跑后台逻辑的推荐位置late_start阶段非阻塞并行执行system.prop可选keyvalue格式的属性由 resetprop 逐条加载开机属性加载阶段sepolicy.rule可选每行一条 SELinux 策略语句开机 sepolicy 打补丁阶段zygisk/可选按 ABI 命名的 Zygisk 原生库如arm64-v8a.soZygote 派生应用进程时注入disable/remove/update自动生成状态标记禁用 / 下次开机移除 / 待升级每次开机 Magisk 扫描时读取vendor、product、system_ext自动生成指向system/对应子目录的符号链接不要手动建安装时由 Magisk 创建三个值得展开的点脚本跑在哪所有模块脚本都在 Magisk 自带的 BusyBoxash里以 standalone 模式执行所以别依赖设备自带的非标准 shell 特性。时机差异post-fs-data.sh在模块挂载之前跑适合在文件被合并进系统前做最后的动态调整service.sh在系统服务起来之后跑绝大多数开机干点活的需求用它就够了。标记文件的原理就是文件存在与否二值开关。Magisk 每次开机扫描/data/adb/modules下的每个目录发现disable就跳过挂载发现remove就执行完uninstall.sh如果有的话后整个删除。这也是临时禁用模块最快的手动姿势touch /data/adb/modules/my_tool/disable然后重启想恢复就删掉这个文件。原理拆解系统是怎么被无感修改的知道了什么时候跑再看为什么改完系统又不留痕。这一节帮你建立完整的开机时间线后面调试时所有现象都能挂到这张图上。开机 | v magiskinit 顶替 init 成为第一个进程 | 挂载早期分区、注入 init 服务、打 sepolicy 补丁 v post-fs-data 阶段/data 解密完成 | 启动 magiskd | 执行各模块的 post-fs-data.sh阻塞40秒上限 | *** 此时模块还没挂载改模块目录来得及 *** | 执行模块的 system 目录 - 合并挂载进真实 /system v late_start 阶段 | 并行执行各模块的 service.sh不阻塞启动 v Zygote 启动 - (若启用 Zygisk) 派生应用进程时注入 zygisk 库 v sys.boot_completed 1几个关键机制合并挂载不是复制。模块的system/通过 overlayfs 或 bind mount 逐层叠到真实系统分区上同路径的文件被替换新路径的文件被添加。真实分区的内容始终原样躺在磁盘里Magisk 卸载后一切照旧——这就是无侵入的由来。整目录替换与删除的暗号。想让某个文件夹整个被换掉而不是逐文件合并在模块内对应文件夹里放一个名为.replace的空文件即可想删除系统里的某个文件则在模块里放一个major0, minor0的哑字符设备mknod 文件名 c 0 0。这两招在替换整个 App 或干掉系统预装组件时非常顺手。脚本时机的坑位差异。再强调一遍时间线里最关键的一格模块挂载发生在post-fs-data.sh执行之后。所以这个脚本里改的是模块自己目录用后文说的MODDIR改的内容会在紧接着的挂载时生效而service.sh里看到的/system已经是合并后的世界。避坑手册新手最常踩的5个坑下面 5 个坑每个都会单独浪费你半天排查时间对照自查一遍。1. ZIP 里多套了一层外层目录。这是模块装了但啥也没发生的头号原因。如果你压缩时选中了整个my_tool文件夹解出来的结构是my_tool/module.prop而不是module.propMagisk 找不到元数据直接当普通 ZIP 处理。正确做法是进到文件夹内部再压缩内容或在命令行里cd my_tool zip -r ../my_tool.zip .2. 发布了模块之后又改 id。id就是模块文件夹名也是唯一标识。改了 id对 Magisk 来说这是一个全新的模块旧模块连同它写下的所有数据都还在原地新 id 从一张白纸开始。id 定下来就别动要换名字只改name。3. 在脚本里硬编码模块路径。/data/adb/modules/my_tool这种写法看起来没错但模块被升级、重命名或目录结构变化时就全断了。所有脚本统一这样取自己的根目录MODDIR${0%/*}安装脚本customize.sh则直接用安装器注入的$MODPATH变量两个场景各有一手写法混用必乱。4. 权限没给对脚本静静地失败。脚本没有执行位、可执行文件丢了0755运行时就是权限拒绝而这类错误经常不弹任何提示。好在安装器解压后会默认设置权限和 SELinux 上下文真正的问题多半出在你自己customize.sh里手动复制文件时忘了跟文件0755、普通数据文件0644可执行文件别超过0755能少折腾就少折腾。5. 等待 boot_completed 写成忙等循环。经典写法是while [ $(getprop sys.boot_completed) ! 1 ]; do sleep 1; done能跑但全程空转浪费 CPU。项目自带的 resetprop 有专门的阻塞等待特性一行顶替整个循环resetprop -w sys.boot_completed 1另外两个相邻的坑一起记了post-fs-data.sh里禁止用setprop改属性会死锁整个启动流程要用resetprop -n以及所有属性操作优先 resetpropsetprop在模块脚本里属于高危动作。进阶路线Zygisk、SELinux策略与模块自动更新基础模块跑顺之后三条线可以按需展开每条都只点到入口Zygisk让代码在 Zygote 派生每个应用进程、应用特化之前注入执行是做应用级拦截和框架增强的正路。把按 ABI 编译好的.so放进模块的zygisk/目录即可被加载脚本里可通过环境变量ZYGISK_ENABLED感知它是否开启。官方示例项目 zygisk-module-sample 是最好的起步参考。sepolicy.rule模块进程被 SELinux 拦了别硬绕在这个文件里每行追加一条策略语句开机时 Magisk 会连同系统补丁一起加载。写语句的格式文档在docs/tools.md的 magiskpolicy 一节。updateJson 自动更新在module.prop里加一行updateJson你的JSON地址指向一个包含version、versionCode、zipUrl、changelog四个字段int、url、string 类型的 JSONApp 就能自动发现新版本并提示更新。收尾资源与调试命令速查回到最开始那句话系统文件没动过所有改动都是开机时叠上去的卸了就是没装过。把前面 5 个坑过完、时间线记熟你手里就已经有完整的模块调试能力了——出问题先magisk --list-modules看模块在不在位再查/data/adb/modules/id/下有没有多出的disable/remove标记最后看挂载后的/system里文件到底对不对。继续深挖的话仓库里这几个位置最值得通读官方完整指南docs/guides.md模块结构、安装器、boot 脚本的权威出处启动流程细节docs/details.mdmagiskinit / magiskd 各阶段做了什么打包辅助脚本scripts/module_installer.shrecovery 刷入时作为 update-binary 使用的入口模块模板与 Zygisk 示例项目magisk-module-template、zygisk-module-sample搜项目名即可找到按这个顺序读完从写module.prop到发版自动更新整条链路上就没有黑盒了。【免费下载链接】MagiskThe Magic Mask for Android项目地址: https://gitcode.com/GitHub_Trending/ma/Magisk创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考