一台闲置安卓手机 + Termux 当免费服务器的幻想,死于六层错位。本文不谈内网穿透(那是大家最先记住的痛,却是最外层、最好解决的一层),专拆"设备本身"这一侧的每一道锁。

一句话结论

Android 的操作系统哲学是"每十秒问一次用户",服务器的哲学是"没人理它,它自己跑"。两套哲学互不兼容。Termux 只是把一个普通 app 的权限尽量放开,并没有把 Android 变成服务器。

第一层:权限模型,根上就错位

Termux 再怎么说,本质是一个普通 app:

  • 进程挂在 u0_a91 这样的 app UID,跑在 SELinux 的 untrusted_app 域
  • 系统全局状态基本不可见:cat /proc/loadavg、/proc/stat 直接 Permission denied(实测,SELinux 拒绝,非 root 无解)
  • 读不了 dmesg、调不了 CPU 频率、改不了系统设置
  • 服务器运维第一件事——"看看机器状态"——在这里就做不到

抽象:服务器运维的"观测权"是地基,Termux 连地基都没有。

第二层:root 这扇门,被焊死

大量"服务器必备"能力只对 root 开放:

  • 绑定 1024 以下端口(需 setcap 或 net.ipv4.ip_unprivileged_port_start)
  • iptables 转发、按进程 cgroup 限流
  • 真正的 chroot、mount、mknod
  • 加载内核模块
  • 全局进程监控

这台机器(骁龙 778G+ / SM7325,内核 5.4.289-qgki)的实际处境:

  • bootloader 锁定 → 无 TWRP → 无 Magisk → 无自定义内核/ROM → root 的标准路径全断
  • 厂商 ROM 连刷机都锁,最后一条路也堵死
  • 于是只能靠 proot-distro:那是 syscall 模拟的"假 root",能跑 apt、装包,但做不了真 root 的事,更装不了 systemd / Docker

抽象:root 在 Android 上不是"更多权限",是"入场券"。锁了 bootloader 等于永不上车。

第三层:进程生命周期站在对立面

服务器要 7×24 无人值守,Android 的一切设计都在消灭后台进程:

  • 没有开机自启,没有真正的 init 服务管理;termux-services(runit)是模拟,termux-boot 要 ROM 放行,国产 ROM 的电池管家随时一刀切
  • Doze、App Standby、厂商省电策略:进程被杀、调度被延迟是常态
  • termux-wakelock 只能拿 wake lock 防 CPU 睡眠,防不了被杀
  • cron 不存在;AlarmManager 不是 crontab,定时任务会延迟、会丢

抽象:你没法承诺"这个进程明天还在"。而"明天还在"是服务器的底线。

第四层:内核与服务器需求错位

移动内核是为手机定制的,不是为服务端定制的:

  • 大量 CONFIG 裁剪,缺模块
  • Docker 需要的 overlayfs、netns、cgroup 挂载基本没有 → Docker 装不了
  • zram swap 存在但不可控
  • 负载完全不可解释(且 Termux 里根本观测不到):实测 load average 13+、三档齐平,但 CPU 800% idle、user 0%、sys 0%。后经 adb 全局视角定位:不是用户进程,是厂商 ROM 内核常年挂 D 状态的 kworker / kdmflush / loop[0-39] / ext4-rsv-conver 内核线程把 load 顶起来的正常基线。移动内核的 load 统计含"不可中断任务",而这些线程只是挂着等设备事件,不占 CPU、不干活。想在 Termux 里解释 load,连读 /proc/stat 的权限都没有。
  • 旗舰 SoC 持续负载 = 热降频 + 电池鼓包风险,越跑越糟

抽象:你不是在调优一台机器,是在一台"不允许你观察、也不允许你控制"的机器上调优。

第五层:网络控制权不在你手里

  • 低端口要特权(见第二层)
  • 系统"全局代理"覆盖不到 Termux:手机开代理,Termux 的 pkg update 照样裸连报错,得自己 export http_proxy
  • WiFi AP 隔离、运营商 CGNAT 都是外部变量(本文不展开,见相关笔记)

抽象:手机的网络栈是"为上网设计的",不是"为被访问设计的"。

第六层:维护是一场持续消耗战

  • ROM 更新可能清空数据分区;bootloader 锁了,连系统级备份回滚都做不到
  • 沙箱 + scoped storage 限制,Termux 数据目录备份迁移麻烦
  • 每次系统升级都可能踩新坑,运维成本高于一台小主机

补充实战:内网穿透下的端口与服务联动(frpc 踩坑实录)

上面第五层说"低端口要特权",frp 实战就是它的直接投影。frp 把"外网→本机"打通后,困住你的往往是本地这一侧的端口错位。

场景:frps 服务端 103.224.80.31:7000(带 auth token),本地一条 HTTPS 隧道挂三个域名 api / vault / new.6767.chat。frpc 的 https 类型代理 = frps 在公网终止 TLS,把 HTTP 转发到 localIP:localPort。

  • 坑 1:localPort 必须指到本地服务真实监听的端口。本地路由网关 ai-6767-gateway(node server.js)监听 127.0.0.1:8443,反代到后端 new-api(127.0.0.1:3000)。为什么不是 443?因为 Termux 非 root 绑不了低端口(第五层),网关只能在 8443。若 frpc localPort 写成 443,公网 TLS 握手直接 Connection refused。
  • 坑 2:判断"真通了"要看业务层。frpc 日志 start proxy success 只代表隧道注册成功;验证方式是公网 curl https://域名 返回 HTTP 200。
  • 坑 3:控制脚本硬编码配置格式。服务控制脚本 frpc-ctl 内硬编码 CONFIG_FILE="~/.config/frp/frpc.json"。新版 frpc 支持 .toml,但直接替换会让启停脚本找不到文件、孤儿进程占住端口。改配置文件格式 = 控制脚本一起改。
  • 坑 4:废弃域名残留。旧域名 ai.6767.chat 在面板已删除,配置若残留,日志会反复报 您的账号下不存在域名为 [ai.6767.chat] 的 HTTPS 隧道,proxy 一直 start error。域名以面板为准,别凭记忆写。

一句话规律:https 类型隧道的 localPort 指向的是"离 Termux 最近的那个 http(s) 服务"的实际端口,不是你想暴露的"理想端口"。Termux 侧凡是跟端口打交道的地方,默认先把"非 root 绑不了 1024 以下"记在心上。

判断框架

想把"能不能在这台安卓上干 X"问清楚,过三个问题:

  1. 需要 root 吗?需要 → 死(这台机器已焊死)
  2. 需要开机自启 / 长驻吗?需要 → 半死(有 hack,但不可靠)
  3. 需要全局状态 / 低端口 / 容器吗?需要 → 死(权限与内核都不给)

三个问题都过了,才轮到"网络通不通"。所以内网穿透反而是最外层的那个问题——它只是最后一道门,不是第一道。

什么能当,什么不能当

能当:

  • 个人跳板:SSH 进来跑脚本、开内网小服务
  • 轻量代理进程、agent 类任务(codex、node 代理这类"睡在那"的进程没问题)
  • 当"客户端"很称职:接 API、手动触发的任务

不能当:

  • 需要可靠自启、定时任务、低端口、Docker、全局监控的"真服务器"
  • 需要长时间无人值守稳定运行的东西

平替:如果真想要个便宜服务器

  • ARM 开发板 / 二手小主机(几十到几百元),是安卓这个坑的平替
  • 或者让手机继续当"客户端",服务器交给真正的服务器

相关


本文归档于个人知识库 · 领域:CS & AI · 模块:04 Project_CS_AI/Network