手上有两台红米 Note 13 5G(型号 2312DRAABC,内部代号 gold,天玑 6080,8+256,HyperOS / Android 15)。这 SoC 没有 Linux 主线内核支持,刷不了原生 Linux 发行版,但 8G 内存 + UFS 256G + 能一直插着电——拿来当 7×24 家庭服务器正好:音乐库离线听、远程可运维、双机互备。
整个折腾历时一周,从解锁 bootloader 到音乐自动同步上线,中间还出了双机重启卡死的事故。这篇把过程和结果完整记一下。
第一步:解锁 bootloader(最危险的一步)
小米官方解锁等待期长、限制多,走的是 Jz8Root 的 MTK RPMB 硬件解锁路线——通过 BROM 用 preloader 直接写 seccfg。但第一原则是先备份一切:动任何东西之前,先把所有 NV 分区(nvram / nvdata / nvcfg / persist / protect1 / protect2 / seccfg / lk / RPMB)用 mtkclient 完整导出来。
nvram/nvdata 丢了就是丢 IMEI 和基带。每台 ~536MB 的备份是砖机或丢 IMEI 时的唯一保险,必须带走。
进 BROM 有一套完整仪式,其中有一条铁律:必须用 USB 2.0 口——USB 3.0 口会静默损坏写入,没有任何报错:
- 手机完全关机
- 同时按住音量+ 和音量−
- 插 USB 线,保持按住 15 秒以上,屏幕必须全黑
- 电脑端出现
0e8d:0003
电脑侧也有坑:要先停掉 ModemManager(它会抢占 MTK 串口)、卸载 option / usb_wwan 驱动。看到 mtkclient 不认的 0e8d:20ff,基本就是这两个没做干净。
BROM 通了之后,流程其实不复杂:
scan_lk.py # → COMPATIBLE_FULL,符合 Path A 硬件解锁条件
da rpmb e ... # 擦除 RPMB magic(这台定位在 sector 65504)
da seccfg unlock # 写入解锁
两个细节:擦掉 RPMB magic 之后、seccfg unlock 之前绝不能碰电源键(preloader 会在任何启动时重写 magic);解锁后首次开机必须擦掉 userdata/metadata,否则直接卡在 dm-verity 的"设备已损坏"界面。fastboot getvar unlocked 返回 yes,两台手机正式离开出厂状态。
第二步:Root——这个机型没有 init_boot
这台机器的特殊之处:没有独立 init_boot 分区,ramdisk 放在 vendor_boot 分区里的 init_boot.cpio 中。所以 Magisk 标准的"修补 init_boot"流程走不通,得改刷 vendor_boot 补丁镜像,而且必须 Magisk v30.7 起步(PR #9370 才加入 vendor_boot 支持),旧版会刷入成功但 root 不生效。
流程:
| |
还有两个坑:
- 本机的提权入口是
/debug_ramdisk/magisk su,/sbin/su、/system/xbin/su都不存在——别据此误判 root 失效 - 开机后第一次
su请求可能被自动拒绝并记住,要到 Magisk 超级用户列表里手动把shell改成「允许」
第三步:裁 HyperOS 冗余(内存从 78MB 到 5G)
出厂状态 HyperOS 只给可用内存留了 78MB。裁剪之后:
| 指标 | 裁剪前 | 裁剪后(重启稳定) |
|---|---|---|
| Mem used | 5366 MB | 2456 MB |
| Mem free | 2212 MB | 5122 MB |
| Swap used | 186 MB | 0 MB |
具体做了这些:
- 禁用约 100 个系统包(全部
pm disable-user,可逆):小爱/AI 全家桶(voiceassist、aiservice、aiasst…)、广告统计(systemAdSolution、analytics…)、应用商店/游戏中心/快应用、云同步/车联/投屏、支付钱包虚拟 SIM、各类测试工具和日志上报 - 卸载 21 个预装垃圾(
pm uninstall -k --user 0):淘宝、闲鱼、拼多多、美团、微博、抖音、快手、今日头条、番茄小说、腾讯视频……保留支付宝、高德、WPS、米家 - hosts 广告拦截:Magisk hosts 模块(yhosts 列表 6428 条,含小米系广告域)
- 关掉负一屏和上滑资讯流(这俩会被系统偷偷重新启用,要重新禁)
踩的坑:
- 第一轮误伤了天气和主题商店,广告 hosts 又误拦了天气域名。后来恢复 4 个包 + 给 hosts 模块加白名单
pm enable状态落盘有延迟,启用后立刻重启会丢失,要等 20 秒再重启- 漂移:重启 5 次后 HyperOS 把 24 个包重新启用了。给
trim-hyperos.sh加了verify模式(只报告不改动)+ KEEP 例外表,以后每次重启后跑一次 verify 自查
第四步:服务器化
目标是 7×24 随时能连、能干活:
- Debian chroot:chroot-distro 模块装 Debian 12 bookworm arm64(rootfs 只有 74MB),里面跑 sshd:2222 + shellinabox(Web 终端)+ glances(监控面板)
- 保持唤醒:写
gold_serverwakelock,防熄屏后 deep doze 挂起系统、掐网络 - 网络调优:TCP BBR + fq qdisc;CPU 最低频锁定(MTK power HAL 开机后会重置,脚本每 30 秒重写 5 分钟对抗);GPU 从锁死的 dummy 调度换到 simple_ondemand
- WiFi 看门狗:每 60 秒 ping 网关,连续 5 次失败自动
svc wifi disable/enable重连——前两天数据链路抽风了 3 次,全部被它自愈 - 80% 充电上限:ACC 模块的守护进程在这个机型上不工作(97% 还在充),自己写了脚本直接写
input_suspend:≥80% 停充、≤60% 恢复。长期插电当服务器,电池健康是刚需
双机重启卡死事故
第二天 13:45,两台手机重启后同时卡死:bootanimation 一直转、sys.boot_completed 为空、zygote 状态 restarting、crash buffer 里全是 zygote64 fork system_server 崩溃(/dev/binder 节点缺失)。magiskd 在跑,但 su 不可用。
排查靠排除法:
- 模块逐个全禁 → 能开机
- Magisk 版本对比(30.7 / 30.6)→ 都卡
- 刷回原厂 vendor_boot → 连续 3 次重启正常(证明 ROM 本身稳定,问题在 Magisk 侧)
- 最终定位:
chroot-sshd-autostart.sh在启动早期把 Debian chroot 挂载进/debug_ramdisk,与 Magisk preinit 机制冲突 → 第二次重启 preinit 挂载异常 → binder 节点缺失 → zygote 起不来
处置:设备 2 降级 Magisk 30.6 + 禁用 chroot 自启脚本,连续多次重启验证通过。
这个事故还顺带挖出一个更隐蔽的地雷:Magisk 的 service.d 按可执行位运行脚本,不看扩展名。文档里写的"禁用 = 改名为 .bak“其实根本没禁——文件还是 -rwxr-xr-x,只是那台恰好 25 小时没重启没暴露。正确做法:文件移出目录、去掉执行位。
远程运维:FRP 双隧道
手机在 CGNAT 后面(4G 公网 IP 一天换 4 次),外网直连无解。方案:手机主动出站连 VPS 上的 frps(就是「我的自建服务清单」里那台),每台开两条隧道:
| 设备 | SSH | adb(保底通道) |
|---|---|---|
| 设备 1 | :6012 | :6014 |
| 设备 2 | :6008 | :6009 |
- SSH 仅密钥认证,全世界任何地方一条
ssh gold2进手机 - adb 隧道是保底通道:即使 Termux 整个被 MIUI 干死,root 层的 adb 依然可进,能修一切。在此之前 Termux 一挂手机就够不着了,只能人肉去插 USB
一个有意思的细节:VPS 的 frps 是 0.51.3(ini 配置),手机 frpc 是 0.71.0(toml 配置),跨 20 个小版本握手正常。但别为此升级 VPS 的 frps——上面挂着 8 条生产隧道(几家店的 SSH、旁路由、远程桌面),升级风险远大于收益。
音乐自动同步链路
手机的主力用途是音乐:/sdcard/Music/音乐U盘 里 682 首 / 6.2GB,Musicolet 离线播。但我想"歌单加歌 → 自动到手机,随时离线听”,于是搭了这条链路:
网易云歌单
│ systemd timer 每 30 分钟
▼
VPS(sync.py:按 song_id 比对线上歌单 ↔ 本地,只下新增)
│ HTTPS 静态分发 + NATS 通知
▼
手机(gold-sync.py --daemon,root 层)
└ 落盘后触发 MediaStore 重扫 → Musicolet 立即可见
几个设计点:
- NATS 只报信,文件走 HTTP 拉:NATS 默认 max_payload 1MB,一首歌 8~12MB;VPS 才 1.6G 内存,开 JetStream 不划算。manifest.json 是唯一真相来源,漏收消息不影响最终一致性(还有 30 分钟轮询兜底)
- 序号对齐重命名(最值的一段逻辑):文件名是
NNN. 歌名 - 歌手.mp3,序号 = 歌单位置。我习惯把新歌加在第一首,加一首 → 后面所有歌序号 +1 → 全部文件名改变。不对齐的话,下载器会重下整个 156 首的歌单(~1.4GB);对齐后是 155 个重命名 + 只下 1 首 - 冷启动匹配:手机里已有 676 首、VPS 全新下载序号不同,首次同步要用"去掉
NNN.前缀的文件名"把本地文件认领回 song_id。且一个本地文件只能被认领一次——歌单里有同名同歌手的重复曲目,认领两次就是对同一文件重命名两次直接崩(实际踩过,99 个文件卡在临时名,写了还原逻辑)
最隐蔽的坑:
- MIUI 会切断非前台应用的网络:Termux 里
curl全返回 000,连直连 IP 都超时;同一时刻 root 和其他应用全部正常。DNS、WiFi、防火墙全排查了一遍才定位。解法是termux-wake-lock,开机脚本第一行必须是它 - 目录名带半角冒号,Android FUSE 拒绝一切写入:歌单目录
Bar 20:30~里那个:是 FAT 非法字符,Termux 写不进去,连 root 都写不进去(root 继承了 app 的挂载命名空间,su -mm也无效)。本地目录改成全角冒号Bar 20:30~,视觉几乎无差别 - Termux:Boot 靠不住:MIUI 会把 Termux 打成
stopped=true,Android 不向 stopped 应用投递BOOT_COMPLETED,Termux:Boot 开机永远不触发。最终把所有守护进程迁到 Magisk service.d(root 层)——开机必跑、永远有网、不受任何应用管理影响
实测端到端:22:07 歌单加歌 → 22:17 VPS 下好 → 22:18 手机下好,全程 11 分钟。
最终结果
| 设备 1 | 设备 2 | |
|---|---|---|
| ROM | OS3.0.9.0 / _b 槽 | OS3.0.10.0 / _a 槽 |
| Root | Magisk 30.7 | Magisk 30.6(30.7 在 3.0.10 上卡开机,刻意降级) |
| 可用内存 | ~5.1GB | ~5.1GB |
| 曲库 | 700 首 / 6.2GB | 700 首 / 6.2GB |
| 远程 | SSH + adb 双隧道(公网) | SSH + adb 双隧道(公网) |
| 限充 | 80% 停充 | 80% 停充 |
| SIM | 无 | 联通 5G SA(数据关闭) |
几个数字:
- 裁剪后内存可用 78MB → 5.1GB
- 音乐自动同步端到端 11 分钟
- 5G 实测(设备 2):下行 24
33Mbps,偏低(联通 5G 正常 100300Mbps,套餐限速或信号,待查) - root 层看门狗统一巡检 sshd / frpc / 同步守护 / 电池限充,每 60 秒,谁挂了谁拉起
另外写了一个 health-check.sh 例行体检脚本,一条命令出完整报告:身份、服务进程数、网络验证状态、全局代理、电池限充、内存、曲库与 MediaStore 对账、修剪漂移。其中"全局代理"一项是后来加的教训:设备 1 残留过一条 http_proxy 127.0.0.1:8080,所有应用断网但 root 完全正常,WiFi 设置界面还显示"已连接",UI 上根本查不到——这种不对称是排查时最大的误导。
最近还给 Termux 装了 musicfox(网易云音乐终端版),配了 Termux:Widget 桌面快捷方式,不用开 app 直接敲命令听歌。后续打算在它们身上试 NAS(OTG 外接存储)和下载节点。
几点收获
- 先备份一切。那两份 ~536MB 的 NV 分区备份是这个项目的保命资产——没有它们,解锁那一步根本不敢做。
- root 层比应用层可靠。所有"开机必须跑"的守护进程放应用层(Termux:Boot)全被 MIUI 干掉,迁到 Magisk service.d 之后零失效。
- “锁文件 + PID” 的单实例写法是重灾区。两个看门狗脚本都因为 PID 复用死锁静默停摆过一天以上(进程死了,PID 被别的进程回收占用,存活检查永远通过)。锁检查必须配合
/proc/<pid>/cmdline核对身份。 - 不要在 adb/ssh 里堆嵌套引号。排查系统状态一律写成脚本文件推上去执行——
su -c '...$(cat ...)...'这种嵌套我把 wakelock 丢失、曲库清零误判了四次,实际都好好的。 - 自建的乐趣在这:每个零件都看得见摸得着,坏了修得快,修完还懂了。
本文由 Qwen3.8-27B(OpenRouter)根据两台设备的接手包文档与会话记录整理撰写,我负责审核与修改。