news 2026/9/11 6:40:19

Termux服务导航页搭建:一键汇总端口与服务入口,告别命令行记忆负担

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Termux服务导航页搭建:一键汇总端口与服务入口,告别命令行记忆负担

在 Termux 里把服务一个接一个跑起来之后,最痛苦的事情其实不是安装配置,而是"我到底开了哪些端口""这个服务管理地址是多少来着"。习惯了记在备忘录里,时间一长自己都看懵了。后来我花了一个下午写了张服务导航页,一次性把 Termux 里跑着的下载服务、Web 服务、API 接口都汇总到一个网页上,手机浏览器一开就是全部入口。今天就把这个方案完整拆一遍,适合那些在 Termux 或者类 Linux 终端环境里部署了不少服务、想用最低成本做个统一入口的折腾型玩家。

1. 在动手之前:先想清楚导航页到底要解决什么问题

1.1 我实际遇到过什么样的"服务混乱"

我在主力安卓手机上装了 Termux 很长时间了,里面跑的东西从最初的 open-ssh 和 Python 脚本,慢慢变成了一个微型服务器:有下载服务、有定时任务、有内网测试接口、偶尔还会临时起一个 Python HTTP Server 传文件。一段时间后,问题就变得很现实:打开浏览器想访问某个服务,却要先去 Termux 里敲命令查 IP、查端口、查路径;有些服务是临时启动的,今天用这个端口明天用那个端口,记性稍微差一点就全靠猜。

后来我还遇到过更尴尬的情况:一个临时起的服务没有关掉,端口被后面的服务占用了,排查半天才发现是之前留下的进程。这种事情本质上不是 Termux 不稳定,而是缺少一个"统一视角"。所以我想的不是装一个重型监控面板,而是做一个纯静态、可自动更新的服务导航页——它只干一件事:把端口、IP、服务名、状态入口整理到一个页面上。

1.2 导航页方案的取舍:为什么不是重型管理面板

有人可能会问,既然 Termux 能装 Nginx 也能跑 PHP 和数据库,为什么不直接用一个现成的导航项目,比如 Heimdall 或者 Dashy?我当时确实考虑过,也装过测试。结论是:在 Termux 这种手机上,追求功能丰富往往意味着资源占用高、依赖复杂、更新频率跟不上 Termux 的软件源节奏。

导航页需求其实很轻:能显示服务名、描述、访问链接,最好有分组和在线状态,这就够了。再往上的功能,比如用户登录、统计、仪表盘,在没有公网 IP 的场景下基本用不上。所以我最终选择的是"静态 HTML + 轻量 Web 服务器 + 自动生成脚本"的组合。更新导航页就是更新时间戳然后重新生成一遍 HTML,服务器只需要负责把文件吐出去,任何性能压力都不存在。

1.3 这套方案最终能覆盖哪些应用场景

把方案想明白后,它的适用范围比想象中广:

  • 内网多服务入口:手机连着家里的 Wi-Fi,导航页绑定局域网 IP,随手一点就能进服务。
  • 临时服务登记:Termux 里临时起的 HTTP 服务、API 调试服务,跑起来的同时顺手写进导航配置,下次打开就知道端口在哪。
  • 设备间互访:平板、电脑、另一台手机可以通过浏览器访问导航页,不用每台设备都装终端。
  • 快速分享:给需要访问某服务的人发一个局域网链接,不用教对方怎么进 Termux 看端口。

它解决的核心问题是"记忆负担"和"查找成本"。与其说它是一个部署项目,不如说它是一个使用习惯的固化。

2. 环境准备:Termux 该装什么、怎么规划目录

2.1 基础环境初始化

开始之前必须确认 Termux 基础环境是干净的。很多导航页装不成功,罪魁祸首其实是包管理器源没更新或者包冲突。初始化建议按顺序执行:

pkg update pkg upgrade -y termux-setup-storage

pkg upgrade 会更新已安装的所有包,首次执行可能耗时较长。这一步不能跳过,因为 Termux 的软件源更新比较频繁,某些依赖包旧版本和新版本差别很大,尤其像 nginx、python 这类核心组件。

termux-setup-storage 是申请存储权限的命令,会创建一个~/storage目录,软链到手机的公共存储空间。导航页的静态文件一般不需要放到公共存储,但我建议把 HTML 文件或脚本备份到公共目录一份,方便用文件管理器查看和编辑。授权以后,即使 Termux 被系统回收,备份文件也还在。

2.2 安装 Web 服务器

导航页需要一个 Web 服务器来对外提供访问。二选一的话,我推荐 Nginx,原因主要有三个:

  • Nginx 配置简单,一个 server 块就能搞定端口、根目录和 index。
  • 它支持 IPv6 和局域网访问很稳定。
  • Termux 官方源里一直有 nginx 的稳定版本,安装和卸载都干净。

安装命令:

pkg install nginx -y

如果只是想临时用一下、不想维护进程,那 Python 自带的 http.server 也可以,但只适合临时演示,不适合长期服务:

python -m http.server 8080

导航页这种场景我强烈建议走 Nginx,因为后面要加开机自启动、设默认首页、做端口转发,Nginx 的体系更成熟。

2.3 目录规划:别把导航页和站点根目录混在一起

我自己踩过一个坑:一开始把导航页 HTML 放在了~/frontend目录,Nginx 的 root 直接指向那里,结果后续想加子页面、换主题、做版本备份时,目录结构变得很乱。后来我重新规划了一套目录,结构清晰很多:

~/nav-site/ # 导航页项目根目录 ├── public/ # 静态文件,Nginx 直接指向这里 │ └── index.html ├── config/ # 服务清单配置文件,纯文本或 JSON └── scripts/ # 自动生成 HTML 的脚本

public是唯一的对外目录,configscripts对用户不可见。这样做好处很明显:改配置不需要动 Nginx 配置,改 HTML 模板不会干扰服务清单数据,备份整个目录也方便。

2.4 必须记住的几个 Termux 文件路径特性

Termux 的目录结构和常规 Linux 略有不同。常规服务器的/var/www/html/etc/nginx这些路径,在 Termux 里是不存在的,也不建议自己强行建立。Nginx 安装后的配置文件路径是$PREFIX/etc/nginx/nginx.conf,这里$PREFIX默认是/data/data/com.termux/files/usr,记不住不要紧,直接用$PREFIX变量就行。

另外,Termux 不支持 systemd,所以服务的启停方式跟服务器不一样。Nginx 装完后,手动启动用nginx,停止用nginx -s stop,重载配置用nginx -s reload。这个点后文会自动启动部分再展开。

3. 服务导航页的完整部署过程

3.1 先用最简单的 HTML 跑通访问链路

我不建议一开始就上脚本自动化。第一步,先手动做一个静态 HTML,确认"浏览器通过手机 IP 能访问到页面"这条链路是通的。

~/nav-site/public/index.html里写一个最基础版本:

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Termux 服务导航</title> <style> body { font-family: sans-serif; background: #f4f4f9; margin: 0; padding: 20px; } .card { background: #fff; border-radius: 8px; padding: 16px; box-shadow: 0 1px 4px rgba(0,0,0,0.1); } .grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 12px; } a { text-decoration: none; color: #1a73e8; font-weight: 500; } .group-title { margin: 24px 0 8px; font-size: 18px; } </style> </head> <body> <h1>局域网服务导航</h1> <div class="grid"> <div class="card"><h3>文件服务</h3><p>本地静态文件服务</p><a href="http://{%IP%}:8070">打开</a></div> <div class="card"><h3>API 测试</h3><p>临时 API 接口</p><a href="http://{%IP%}:8080">打开</a></div> </div> </body> </html>

{%IP%}是手动占位符,等下要用脚本替换成手机当前 IP。

然后配置 Nginx 的 server 块,让访问 8096 端口时指向这个页面。之所以用 8096,是因为避开常见的 8080、8000、8888,它们很容易被其他服务占用。

3.2 Nginx 关键配置:server 块和路径权限

Nginx 主配置在$PREFIX/etc/nginx/nginx.conf。运行vimnano打开后,在http块内增加一个 server 配置。我的完整配置如下:

server { listen 8096; root ~/nav-site/public; index index.html; location / { try_files $uri $uri/ =404; } }

有两点要特别注意。

第一,root不要用绝对路径/data/data/com.termux/files/usr/...硬编码,虽然 Nginx 能识别,但一旦 Termux 重装或迁移,路径会失效。~符号在 Nginx 配置里有特殊含义,所以最好写明确路径:

root /data/data/com.termux/files/user/nav-site/public;

等等,files下的目录名是home,不是user。正确的绝对路径是:

/data/data/com.termux/files/home/nav-site/public

如果不想记这么长路径,可以在 nginx.conf 开头定义一个变量,但我不建议新手这样折腾。直接用绝对路径最省心。

第二,权限问题。Termux 里 Nginx 默认以当前用户运行,所以文件权限不要随意 chmod 成 777。只要目录可进入、文件可读即可。我一般用chmod 755 directory && chmod 644 file

配置完成后测试并重载:

nginx -t nginx -s reload

然后用浏览器访问http://127.0.0.1:8096,能在手机上看到导航页,说明第一步通了。

3.3 用脚本把服务清单变成导航页

手动 HTML 的问题在于:每加一个服务都要改一次 HTML。干脆写一个 Shell 脚本,从配置文件读取服务列表,自动生成 HTML。这里我选择用最简单的 C-style shell 加 sed 模板替换,不依赖 Python 之外的运行时——其实 Python 也在 Termux 里常用,所以二选一都行。

我最终用了 Python 脚本,理由是:处理 JSON、HTML 字符串拼接更直观,转义问题少。

配置文件~/nav-site/config/services.json示例:

{ "groups": [ { "name": "下载与传输", "services": [ {"name": "aria2 RPC", "desc": "下载任务管理", "port": 6800, "path": "/web"} ] }, { "name": "开发测试", "services": [ {"name": "API Mock", "desc": "接口模拟服务", "port": 8080, "path": "/docs"} ] } ] }

然后写一个 Python 脚本~/nav-site/scripts/build_nav.py,读 JSON,生成 HTML。核心逻辑大致如下:

#!/data/data/com.termux/files/usr/bin/python import json, socket, datetime, os BASE_DIR = os.path.expanduser("~/nav-site") CONFIG = os.path.join(BASE_DIR, "config/services.json") OUTPUT = os.path.join(BASE_DIR, "public/index.html") def get_lan_ip(): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: s.connect(("8.8.8.8", 80)) ip = s.getsockname()[0] except Exception: ip = "127.0.0.1" finally: s.close() return ip def build_html(data, ip): cards = "" for group in data["groups"]: cards += f'<div class="group-title">{group["name"]}</div>\n<div class="grid">\n' for svc in group["services"]: url = f"http://{ip}:{svc['port']}{svc.get('path', '')}" cards += f'<div class="card"><h3>{svc["name"]}</h3><p>{svc.get("desc", "")}</p><a href="{url}" target="_blank">打开</a></div>\n' cards += '</div>\n' return cards if __name__ == "__main__": with open(CONFIG, "r", encoding="utf-8") as f: data = json.load(f) ip = get_lan_ip() html = f"""<!DOCTYPE html>...{build_html(data, ip)}...""" with open(OUTPUT, "w", encoding="utf-8") as f: f.write(html) print(f"[{datetime.datetime.now()}] generated -> {OUTPUT} IP: {ip}")

生成后直接覆盖index.html,然后不需要重载 Nginx,因为 Nginx 直接读文件系统,静态文件变更即时生效。

这个脚本的最大价值:以后新增服务和端口,只需要改 JSON,然后跑一次脚本,导航页就更新了。如果你愿意,还可以把这个命令绑定到 Termux 快捷键或者自动任务里。

3.4 自动探测端口是否在线:让导航页带上状态

单纯的链接在服务挂掉之后还显示在线,会误导访问者。我给脚本加了一个轻量探活:用 socket 去连每个服务的 IP+端口,能连通就打上"在线"标记,连不上就显示"离线",这样打开导航页就能知道服务状态,不用点进去才发现报错。

探活要注意超时不能太长,我设置为 0.5 秒,避免因为某个服务无响应导致整个生成脚本卡死。

def check_port(ip, port, timeout=0.5): import socket as _s s = _s.socket(_s.AF_INET, _s.SOCK_STREAM) s.settimeout(timeout) try: s.connect((ip, port)) s.close() return True except Exception: return False

状态显示我做成"● 在线"和"○ 离线"两个样式,视觉上容易分辨。需要注意:探活只是 TCP 层级的连通性检测,能说明端口在监听,但不代表服务功能完全正常,所以状态信息定位为"参考值"就好,别用来做关键监控。

4. 访问、自启动与联动:让导航页真正好用起来

4.1 局域网访问:手机 IP 和端口要配对

Termux 跑在手机上,要访问导航页,最关键的是知道手机在局域网里的 IP 地址。我之前用上面的脚本来自动获取,这里再单独拆解一下获取 IP 的方式。

虽然不是所有网络都允许 UDP 连接,但用 socket 连 8.8.8.8 的方式在大多数安卓手机上都能返回真实内网 IP。还有一种备选方案:

ip -4 addr show wlan0 | grep inet | awk '{print $2}' | cut -d/ -f1

这个命令需要确保 Termux 有网络权限。组合使用更稳:优先用termux-wifi-connectioninfo(需要安装 termux-api),它会返回比 socket 猜测更准确的 Wi-Fi 信息。

浏览器访问地址就是http://手机IP:8096。如果是电脑访问,确保电脑和手机在同一个 Wi-Fi 下,不用额外设置防火墙——Termux 里的 Nginx 默认监听所有网卡,不像桌面 Linux 有复杂的 firewalld/ufw 干预。

4.2 开机自启动:用 Termux-services 管理 Nginx

Termux 没有 systemd,但官方提供termux-services工具来管理用户级服务。具体流程:

pkg install termux-services -y mkdir -p $PREFIX/var/service

然后为 Nginx 建立一个服务目录。Termux-services 使用的 runit 管理方式,会按目录里的 run 脚本启动进程。我先创建目录:

mkdir -p ~/.termux/service/nginx

不过更标准的方式是使用$PREFIX/var/service/nginx。网上很多教程不再赘述,我直接给出可行的方案:

mkdir -p $PREFIX/var/service/nginx cat > $PREFIX/var/service/nginx/run <<'EOF' #!/data/data/com.termux/files/usr/bin/sh exec nginx -g 'daemon off;' EOF chmod +x $PREFIX/var/service/nginx/run

nginx -g 'daemon off;'表示以前台模式运行,让 runit 能持续监控进程。如果 Nginx 退出,runit 会自动拉起。

重启 Termux 或者手机后,Nginx 会自动启动。这个机制非常稳,我实测过多次。但要提醒一句:termux-services的自动启动是否生效,取决于 Termux 进程是否被杀。国产安卓系统杀后台严重,建议在系统设置里把 Termux 的自启动、电池白名单都打开。

4.3 定时刷新导航页:让状态信息保持新鲜

服务状态和 IP 都可能变化,所以导航页最好能定期更新。Termux 自带cronie可以用,但我不建议频繁跑探活脚本,因为每次探活会建立大量 TCP 连接,影响耗电和网速。折中方案:每 10 分钟更新一次 IP 和状态。如果 IP 没变化,只更新状态;如果 IP 变了,重新生成整页。

安装 cronie:

pkg install cronie -y sv-enable crond

然后写一个 cron 任务:

*/10 * * * * /data/data/com.termux/files/usr/bin/python ~/nav-site/scripts/build_nav.py >> ~/nav-site/logs/generate.log 2>&1

注意 cronie 的 PATH 可能很短,脚本里尽量写绝对路径,或者脚本开头显式设置 PATH:

export PATH=/data/data/com.termux/files/usr/bin:$PATH

这样即使 cron 环境变量有问题,也能调起 Python。

4.4 安全加固的几点建议

Termux 服务默认没有登录校验,如果有人在你所在的局域网里扫端口扫到 8096,那就直接看到了导航页。我的处理方式:

  • 导航页只显示服务名称和链接,不显示敏感端口含义或密码。
  • 对某些服务,在 Nginx 层加 basic auth。
  • 不把导航页直接暴露到公网,如需外网访问,用 SSH 隧道转发到本地端口。

在 8096 端口上增加 basic auth 的配置:

location / { auth_basic "Nas Nav"; auth_basic_user_file /data/data/com.termux/files/home/nav-site/config/htpasswd; ... }

htpasswd 文件生成需要安装apache2-utils里的工具,但 Termux 源里不一定有,可以直接用 Python 生成哈希。不过 basic auth 在局域网访问场景下有点重,很多用户不设。我的建议是最少给导航页加一个访问密码,防止邻居或者公共 Wi-Fi 下其他人误入。

5. 踩坑实录与排查技巧

5.1 Nginx 启动失败,提示"address already in use"

这是最常遇到的问题。通常原因是有其他进程占用了 8096 端口,或者上一次 Nginx 没有正常退出。排查方式:

pkg install nmap nmap 127.0.0.1 -p 8096

如果发现端口被占用,用lsof -i :8096查看进程,或者直接杀掉旧进程:

pkill -f "nginx"

然后重新启动。更稳妥的做法是在配置里换一个不常用的端口,避开 8080、8090 这类热门段。

5.2 浏览器访问导航页显示 403 Forbidden

403 大部分原因是权限问题,不是配置问题。检查两步:

  • 目录权限:~/nav-site/public和上级目录是否可执行权限(755 即可)。
  • Nginx worker 进程的用户是否有权限读取 public 下文件。

Termux 里 Nginx 以当前用户运行,所以一般不是用户问题,更多出现在目录路径打错或者配置文件里 root 指向错误。用一个命令快速验证:

ls -ld ~/nav-site ~/nav-site/public chmod -R o+rX ~/nav-site

o+rX很实用,X 只给目录加执行权限,不改变文件的执行位。

5.3 手机息屏后服务就断了

安卓系统会杀后台进程,Termux 如果在前台运行还没事,一旦切到后台超过几分钟,Nginx 就可能被杀。这个问题不能完全靠 Termux 内部解决,但有几个缓解手段:

  • 锁屏时保持 Wi-Fi 连接。
  • 在系统设置中允许 Termux 后台活动、关闭电池优化。
  • 使用 Termux 的termux-wake-lock来持有唤醒锁:
pkg install termux-api -y termux-wake-lock

执行后 Termux 会一直持有 wakelock,理论上不是太老的安卓系统都能有效防止杀进程。缺点是比较耗电,所以我只在需要长期跑服务的时候开启。

也可以termux-wake-unlock释放,配合 cron 或 Termux:Boot 在特定时段开关。

5.4 IP 变了之后导航页还显示旧 IP

监听变更的推荐方案是扫描网卡并生成,而我遇到过一个问题:脚本通过8.8.8.8连接获取 IP,但当手机网络切换到 5G 热点或者其他不联网的 AP 时,这个 socket 连接可能失败,返回 127.0.0.1。这种情况下导航页就废了。

我有两个兜底方案:

  • 优先读termux-wifi-connectioninfo的 JSON 结果,拿不到再走 socket 探测。
  • 如果拿不到局域网 IP,干脆不生成链接,只显示服务列表,同时标注"未检测到网络"。

这样即使网络环境变化,页面也不会给出一堆错误链接。

5.5 端口冲突多,管理混乱

后装的服务可能默认监听 8000、8080 等端口,跟导航页没关系,但会导致混乱。我的经验是给所有服务分配固定端口段:

  • 8000-8099:Web 类服务
  • 6800:aria2 RPC
  • 5000:开发调试 API
  • 9273:监控面板

把这些端口登记到services.json的 desc 字段里,生成导航页时自动带上。时间长了你会发现,端口规划其实比页面样式重要得多。

5.6 附:快速排障命令清单

症状先试命令再考虑的方向
无法访问导航页nginx -t检查监听端口和防火墙
页面显示离线python ~/nav-site/scripts/build_nav.py看日志确定探活失败原因
服务时好时坏sv status $PREFIX/var/service/nginx检查 runit 状态,看日志
想换端口修改 nginx.conf 并 reload同步改 services.json

最后再分享一点个人经验

我在做这套导航页之前,一直觉得把服务入口做成静态页面有点原始。但实际用下来,反而觉得这种"笨办法"最耐用。它不依赖数据库,不怕 Python 版本升级,不要求额外维护面板服务,顶多就是几个 HTML 和 JSON 文件。如果你在 Termux 里跑的服务数量超过五个,真的值得花一小时搭一个这样的导航页。后续想扩展也不难,比如给页面加上关键词搜索、按标签筛选,或者把服务在线状态用颜色小圆点标出来,这些都是纯前端就能搞定的事。我的建议是先把最基础的跑通,再根据自己使用习惯一点一点加上去,这样维护起来不累,页面也不会越改越复杂。

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

鸿蒙PC虚拟机实测:从Windows迁移的真实体验

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 6:39:51

MicroPython软件看门狗:带状态恢复的三级超时防护框架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 6:37:47

PCB AOI检测系统重构:YOLOv11+轻量大模型协同实战

1. 项目概述&#xff1a;这不是又一个YOLO调参实验&#xff0c;而是一次面向真实产线的检测系统重构你有没有在电子厂的AOI&#xff08;自动光学检测&#xff09;工位前站过&#xff1f;传送带上的PCB板以每分钟12块的速度滑过镜头&#xff0c;上面密密麻麻排布着0201封装的电阻…

作者头像 李华
网站建设 2026/9/11 6:37:32

Swagger接口文档自动化生成测试用例的技术实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 6:35:56

OpenCore Legacy Patcher 3 阶段终极实战:让老 Mac 跑上最新 macOS

OpenCore Legacy Patcher 3 阶段终极实战&#xff1a;让老 Mac 跑上最新 macOS 【免费下载链接】OpenCore-Legacy-Patcher Experience macOS just like before 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher 你的 Mac 停在最后一个官方支持…

作者头像 李华