Files
ykxmz/_build/setup_port_9100.py
T
xmz7891 1d368979aa 2.2.0:手表端连上后先到「远控 / 静默更新被控端」选择页
== 用户要求 ==

"安卓那个逻辑也要改一下,就是你输入配对码后,进入一个页面,
 页面有两个按钮,第一个按钮是远控,第二个按钮是静默更新被控端"

== 做成什么样 ==

新增 choicePanel,连接成功后先进这一页:

    已连接「电脑名」
    电脑端 2.1.5 → 可更新到 2.2.0

    [        远控        ]   <- 第一个按钮
    [   静默更新被控端    ]   <- 第二个按钮

按钮顺序按用户说的来(远控在前)。

页面顶上显示电脑名和**电脑端当前版本** —— 用户之前要求
"手表端连接那个电脑端也可以查看电脑端目前所处的版本",
这里是最自然的展示位置(不弹框,只显示一行)。

为什么不让它直接进控制页:老版本的被控端可能缺功能或有 bug,
"先更新再远控"是更合理的顺序 —— 但不强制,给用户自己选。

== 一个刻意不改的地方 ==

自动切到中转服务器**恢复**时的 `showControlPanel()` **没动** ——
用户本来就在远控页,中途弹一层选择页会打断他。
测试里专门断言了这一点,免得以后有人"顺手统一一下"改坏。

== 顺手修的几个问题 ==

1. **忘了定义 lastDeviceName** —— 写选择页时凭直觉用了这个变量,
   编译报"找不到符号"。补上字段并在连接回调里赋值。
   (教训:写代码时要用的变量,先确认它存在。)

2. **泄漏闸门拦下我自己** —— 这两天写的一批服务器诊断/配置脚本里
   硬编码了服务器 IP(26 处,5 个文件)。规则是 IP 不能进任何
   被跟踪的文件。已全部改成占位符,真实值仍从
   _build/.lightsail_host(已 gitignore)读。

3. **verify_all.ps1 删掉「锁屏时记 SKIP」的逻辑** ——
   用户明确要求删。那个好意带来一个更糟的后果:锁屏时几关根本不跑,
   回归"全绿"了但关键测试其实一跳而过。
   **"因为环境不满足所以不测"比"测了发现失败"更危险。**
   删掉之后果然暴露出 3 个 FAIL —— 屏幕解锁后重跑全部通过,
   确认是环境问题而不是代码问题。

== 服务器这边(不在这份提交里,但同一天做的)==

  * nginx 按用户要求重排:
      IP(80) 任何路径 -> 404(没东西)
      域名 / -> 官网;/zhongzhuanzhan -> 中转站设置
      9100 -> 同样的内容(等 AWS 开防火墙)
  * 删掉早年 Cloudflare Tunnel 的 systemd 残留
  * **补上 ACME 挑战例外** —— 这是最要紧的一条:
    80 端口原来把所有请求都 301 到 https,包括
    /.well-known/acme-challenge/,**续期时会失败**。
    而且它是延迟爆发的(最长 90 天后证书到期才暴露)。
  * 清理 1Panel 安装包残留(223MB)

== 验证 ==

    全量回归 21 关全部 PASS(零 FAIL,桌面可用状态)
    Java 编译通过(android-34, --release 8)
    623+ Python 文件语法通过
    泄漏闸门通过
    全部产物重建,Win7 兼容校验通过
2026-10-10 17:13:24 +08:00

213 lines
9.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
r'''服务器整理:删隧道残留 + 加 9100 监听 + 修"用 IP 访问 404"。
== 用户的要求 ==
* "为什么中转站里还有隧道,所有没的东西就删了"
* "网站官网不是 <服务器IP> 吗,改成 <服务器IP>:9100,中转站也一样"
* "我感觉网站还是不稳定"
== 查到的现状 ==
* `lanremote-tunnel` / `cloudflared` 两个单元 **inactive dead**,
但**单元文件还在**(`systemctl list-units --all` 能列出来)。
那是早年走 Cloudflare Tunnel 时留下的,现在早就换成
nginx + Let's Encrypt 直连了 —— 属于"没的东西",该删。
* **用 IP 直接访问 `http://<服务器IP>/` 返回 404** ——
因为唯一的 80 站点是 `server_name yk.xxmxxs.top`,
Host 不匹配时 nginx 拿它当 default server,转给 relay,
relay 不认这个 Host 就 404。
**这很可能就是"感觉不稳定"的来源**:用域名是对的,用 IP 就不对。
* 9100 端口**服务端没监听、AWS 防火墙也没开** —— 两头都要做。
== 这一版做什么 ==
1. **删掉两个隧道单元**(先 stop + disable + 删文件 + daemon-reload)
2. **nginx 加 9100 监听**:
* `http://<服务器IP>:9100/` 直接出官网
* 中转接口也在 9100 上(`/v1/...`、`/download/...`)
⚠ 这需要 **AWS Lightsail 控制台里开放 9100**,
只有用户能做(我没有他的 AWS 凭据)。
3. **修 IP 访问 404**:给 80 端口加一个 default server,
把不认识的 Host 也送到同一套后端 —— 这样 `http://IP/` 能用。
== 为什么 9100 用 HTTP 而不是 HTTPS ==
IP 地址**没法签证书**(Let's Encrypt 不给纯 IP 签)。
所以 `https://<服务器IP>:9100` 会报证书错。
9100 定位是"Cloudflare 出问题时的直连备用通道",
用 HTTP 就行 —— 中转的数据本身有自己的校验。
'''
from __future__ import annotations
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT / "_build"))
from lssh import run, upload # noqa: E402
# ---------------------------------------------------------------- nginx 片段
# 在 ykxmz 站点的 443 server 里补 9100 监听,并加一个 80 的 default server。
#
# 为什么加在**同一个文件**里:这样只有一份 server 块要维护,
# 后端地址(127.0.0.1:13245)只写一次,改后端不用改两处。
EXTRA_LISTEN = """
# ---- 9100:Cloudflare 之外的直连通道 ----
#
# 用户要求:"网站官网不是 <服务器IP> 吗,改成 <服务器IP>:9100"。
#
# ⚠ 用 IP 没法签证书(Let's Encrypt 不给纯 IP 签),所以这里是 HTTP。
# 定位是备用通道:Cloudflare 出问题时还能直接连上。
#
# ⚠ 还需要在 **AWS Lightsail 控制台**开放 9100 端口 ——
# 光配 nginx 没用,外面照样连不上(实测 9100 现在不通)。
listen 9100;
listen [::]:9100;
"""
DEFAULT_SERVER = """
# ======================================================================
# 80 端口的默认站点
# ======================================================================
#
# 为什么需要它:原来唯一的 80 站点是 `server_name yk.xxmxxs.top`。
# 用 IP 直接访问(`http://<服务器IP>/`)时 Host 不匹配,
# nginx 就拿这个站点当 default server,把请求转给 relay ——
# relay 不认这个 Host,返回 404。
#
# **这很可能就是"感觉网站不稳定"的来源**:用域名是对的,用 IP 就 404,
# 用户不知道区别,只会觉得"时好时坏"。
#
# 现在显式指定一个默认站点:不管什么 Host,都送到同一套后端。
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
access_log /var/log/nginx/ykxmz_default_access.log;
error_log /var/log/nginx/ykxmz_default_error.log;
# 用 IP 访问时不要跳 https —— IP 没证书,跳过去浏览器会报警告,
# 用户会以为网站坏了。直接给内容。
client_max_body_size 64m;
server_tokens off;
location / {
proxy_pass http://127.0.0.1:13245;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 300s;
proxy_connect_timeout 30s;
}
}
"""
def main() -> int:
print("=" * 62)
print(" 服务器整理:删隧道 + 加 9100 + 修 IP 访问")
print("=" * 62)
print()
# ---------------------------------------------------------------- 1. 删隧道
print("── 1. 删掉隧道残留 ──")
r = run(r'''
for u in lanremote-tunnel cloudflared lanremote-relay; do
if systemctl list-unit-files 2>/dev/null | grep -q "^$u"; then
echo " 处理 $u"
sudo systemctl stop $u 2>/dev/null
sudo systemctl disable $u 2>/dev/null
sudo rm -f /etc/systemd/system/$u.service \
/lib/systemd/system/$u.service \
/etc/systemd/system/multi-user.target.wants/$u.service 2>/dev/null
fi
done
# 还有没有别的相关残留
sudo find /etc/systemd/system /lib/systemd/system -maxdepth 2 \
-iname "*lanremote*" -o -iname "*cloudflared*" -o -iname "*tunnel*" 2>/dev/null \
| while read f; do echo " 删 $f"; sudo rm -f "$f"; done
sudo systemctl daemon-reload
echo " --- 之后还剩什么 ---"
systemctl list-units --all --no-pager --plain 2>/dev/null \
| grep -iE 'lanremote|cloudflared|tunnel' | sed 's/^/ /' || echo " (干净了)"
''', timeout=180, quiet=True)
print(r[1] if isinstance(r, tuple) else r)
# ---------------------------------------------------------------- 2. 改 nginx
print()
print("── 2. nginx:加 9100 监听 + 80 默认站点 ──")
r = run("sudo cat /etc/nginx/sites-available/ykxmz", timeout=90, quiet=True)
conf = r[1] if isinstance(r, tuple) else str(r)
if "listen 9100" in conf:
print(" 9100 已经配过了")
else:
# 在 443 那个 server 块的 listen 后面插 9100
anchor = " listen 443 ssl; # managed by Certbot"
if anchor not in conf:
# 换一个可能的形式
import re
m = re.search(r"\n(\s*)listen 443[^\n]*\n", conf)
if not m:
print(" ✗ 找不到 443 的 listen 行")
return 1
anchor = m.group(0).strip()
conf = conf.replace(anchor, anchor + "\n" + EXTRA_LISTEN.rstrip(),
1)
conf = conf.rstrip() + "\n" + DEFAULT_SERVER
tmp = ROOT / "_build" / "_nginx_ykxmz.conf"
tmp.write_text(conf, encoding="utf-8", newline="\n")
upload(str(tmp), "/tmp/ykxmz.conf.new")
tmp.unlink(missing_ok=True)
r2 = run(
"sudo cp /etc/nginx/sites-available/ykxmz "
"/etc/nginx/sites-available/ykxmz.bak.$(date +%s) && "
"sudo mv /tmp/ykxmz.conf.new /etc/nginx/sites-available/ykxmz && "
"sudo nginx -t 2>&1 | tail -3", timeout=180, quiet=True)
out = r2[1] if isinstance(r2, tuple) else str(r2)
print(" " + out.replace("\n", "\n "))
if "successful" not in out:
print(" ✗ 配置有错,撤回")
run("sudo cp $(sudo ls -t /etc/nginx/sites-available/ykxmz.bak.* "
"| head -1) /etc/nginx/sites-available/ykxmz", timeout=90,
quiet=True)
return 1
print(" ✓ 已写入并备份")
print()
print("── 3. 重载 nginx ──")
r = run("sudo systemctl reload nginx && sleep 1 && systemctl is-active nginx",
timeout=120, quiet=True)
print(" nginx: " + (r[1] if isinstance(r, tuple) else str(r)).strip())
# ---------------------------------------------------------------- 4. 复核
print()
print("── 4. 复核 ──")
r = run(r'''
echo " --- 监听端口 ---"
sudo ss -tlnp 2>/dev/null | grep -E ':(80|443|9100) ' | sed 's/^/ /'
echo " --- 用 IP 访问(不带 Host)---"
curl -s -o /dev/null -w " http://127.0.0.1/ -> %{http_code} %{size_download} 字节\n" --max-time 10 http://127.0.0.1/
curl -s -o /dev/null -w " http://127.0.0.1:9100/ -> %{http_code} %{size_download} 字节\n" --max-time 10 http://127.0.0.1:9100/
echo " --- 用域名访问 ---"
curl -s -o /dev/null -w " https://yk.xxmxxs.top/ -> %{http_code} %{size_download} 字节\n" --max-time 15 https://yk.xxmxxs.top/
curl -s -o /dev/null -w " /v1/health -> %{http_code}\n" --max-time 15 https://yk.xxmxxs.top/v1/health
''', timeout=180, quiet=True)
print(r[1] if isinstance(r, tuple) else r)
print()
print(" ⚠ 还需要你在 **AWS Lightsail 控制台**里开放 9100 端口:")
print(" 实例 -> 联网 -> IPv4 防火墙 -> 添加规则 -> 自定义 -> TCP 9100")
print(" 光配 nginx 没用,外面照样连不上。")
return 0
if __name__ == "__main__":
sys.exit(main())