mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 16:00:43 +00:00
用户买了 AWS Lightsail(2G 内存 / 2 vCPU / 60G SSD / 公网 IP
13.54.30.196),中转从随身 WiFi 那台小机器搬过去。
== 为什么这次搬迁解决了一堆老问题 ==
原机器(Debian aarch64、460MB、走 4G)一直有几件搞不定的:
* 线路对 Cloudflare 隧道的 **7844 端口间歇性阻断**(443 通、7844 不通),
隧道每 3~10 分钟掉一次、公网跟着 530 —— 查了很久才从
cloudflared 自己的 precheck 里看清
* 只有 460MB 内存
* 会掉电硬挂(实测 2026-10-08 18:42 一次非正常关机)
新机器**有公网 IP**,中转直接监听,不经隧道、不过 7844。
实测公网延迟从 **1000~2000 ms 降到 1.1 ms**。
== 代码改动 ==
1. **relay.py 的 DATA_DIR 默认值不再写死**
原来是 /root/lanremote-relay。新机器上服务以 admin 普通用户跑
(它没理由要 root),而 /root 是 0700 —— 部署时直接
PermissionError: '/root/lanremote-relay'。
改成"本脚本所在目录下的 data/",搬到哪都跟着走。
2. **客户端支持"没有证书的中转"**
新服务器是明文 HTTP(没签证书),而两个客户端原来都往 https 走:
* 手表端:裸 IP 会被强制补 https:// -> 永远连不上,
报的还是 SSL 错误,很容易让人白查半天证书
* Android 9+ 默认禁止明文流量,没 usesCleartextTraffic
请求会被系统直接掐掉
Windows 端本来就是对的(正则里把任意纯 IP 都当"用明文")。
现在手表端规则和它一致,并加了 usesCleartextTraffic。
3. 清掉电脑端一段函数内的重复代码(return 之后还有一份拷贝,
缩进仍在函数体内所以不报错,但读起来很迷惑)。
== 新服务器上的部署 ==
/opt/ykxmz-relay/ 服务端(relay/admin/landing/showcase)
ykxmz-relay.service 监听 0.0.0.0:13245
ykxmz-monitor.service/.timer 每 60 秒查公网,连续 3 次不通就叫预案
rescue-lightsail.sh 四级阶梯抢救(重启中转 / 强杀重拉 /
查防火墙 / 重启整机[默认关])
预案针对新架构重写过:原来围着隧道转(重启隧道、重施 MSS/MTU),
现在没有隧道,改成重启中转 + 查端口/防火墙。
全量回归 46 个阶段全部通过。
103 lines
3.6 KiB
Python
103 lines
3.6 KiB
Python
# -*- coding: utf-8 -*-
|
|
r'''看一眼 Lightsail 上中转服务器的完整状态。
|
|
|
|
为什么写成文件:用 `python -c @"..."@` 传带 `$(...)` 和引号的远端命令,
|
|
PowerShell 会做变量插值、还会在本机执行 `$(systemctl ...)`
|
|
(报 "无法将 systemctl 项识别为 cmdlet")。凡是超过两行的远端命令,
|
|
一律写成文件跑。
|
|
|
|
用法:
|
|
python _build/check_lightsail.py
|
|
python _build/check_lightsail.py --fix # 顺便修文件属主
|
|
'''
|
|
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 # noqa: E402
|
|
|
|
PORT = "13245"
|
|
PUBLIC = "http://13.54.30.196:%s" % PORT
|
|
RELAY_DIR = "/opt/ykxmz-relay"
|
|
|
|
REMOTE = r'''
|
|
R=__DIR__
|
|
P=__PORT__
|
|
echo "════ 服务 ════"
|
|
for s in ykxmz-relay ykxmz-monitor.timer; do
|
|
printf ' %-24s %s\n' "$s" "$(systemctl is-active $s 2>&1)"
|
|
done
|
|
|
|
echo
|
|
echo "════ 健康 ════"
|
|
printf ' %-24s %s\n' "本机 health" "$(curl -s -o /dev/null -w '%{http_code}' --max-time 8 http://127.0.0.1:$P/v1/health)"
|
|
printf ' %-24s %s\n' "公网 health" "$(curl -s -o /dev/null -w '%{http_code}' --max-time 15 __PUBLIC__/v1/health)"
|
|
printf ' %-24s %s\n' "公网首页" "$(curl -s -o /dev/null -w '%{http_code}' --max-time 15 __PUBLIC__/)"
|
|
printf ' %-24s %s\n' "本机延迟" "$(curl -s -o /dev/null -w '%{time_total}s' --max-time 8 http://127.0.0.1:$P/v1/health)"
|
|
printf ' %-24s %s\n' "公网延迟" "$(curl -s -o /dev/null -w '%{time_total}s' --max-time 15 __PUBLIC__/v1/health)"
|
|
|
|
echo
|
|
echo "════ 首页角标 ════"
|
|
echo " 最新版: $(curl -s --max-time 10 http://127.0.0.1:$P/ | grep -o '最新版 [0-9.]*' | head -1)"
|
|
|
|
echo
|
|
echo "════ 监听 / 进程 ════"
|
|
ss -tlnp 2>/dev/null | grep ":$P " | sed 's/^/ /'
|
|
ps -eo pid,rss,etime,cmd --sort=-rss 2>/dev/null | grep 'relay\.py' | grep -v grep | head -2 | sed 's/^/ /'
|
|
|
|
echo
|
|
echo "════ 监测单元 ════"
|
|
cat $R/monitor_state.txt 2>/dev/null | sed 's/^/ /'
|
|
echo " --- monitor.log 尾部 ---"
|
|
tail -4 $R/monitor.log 2>/dev/null | sed 's/^/ /'
|
|
|
|
echo
|
|
echo "════ 抢救报告 ════"
|
|
echo " 共 $(ls $R/rescue_reports 2>/dev/null | wc -l) 份"
|
|
ls -la $R/rescue_reports/ 2>/dev/null | tail -n +4 | awk '{print " " $6" "$7" "$8" "$9}'
|
|
|
|
echo
|
|
echo "════ 知识库 ════"
|
|
if [ -f $R/rescue_knowledge.md ]; then
|
|
echo " $(wc -l < $R/rescue_knowledge.md) 行"
|
|
else
|
|
echo " (还没有)"
|
|
fi
|
|
|
|
echo
|
|
echo "════ 资源 ════"
|
|
free -m 2>/dev/null | sed -n 2p | awk '{printf " 内存 %s/%s MB\n", $3, $2}'
|
|
df -h / | tail -1 | awk '{printf " 磁盘 %s 用 %s\n", $2, $5}'
|
|
uptime | sed 's/^/ /'
|
|
|
|
echo
|
|
echo "════ 定时器下次触发 ════"
|
|
systemctl list-timers ykxmz-monitor.timer --no-pager 2>/dev/null | head -3 | sed 's/^/ /'
|
|
|
|
echo
|
|
echo "════ 文件属主(admin 要能写日志)════"
|
|
ls -la $R/*.log $R/monitor_state.txt 2>/dev/null | awk '{print " " $3":"$4" "$9}'
|
|
'''
|
|
|
|
|
|
def main() -> int:
|
|
if "--fix" in sys.argv:
|
|
print(" ── 修属主 ──")
|
|
out = run("sudo chown -R admin:admin %s && sudo chmod 755 %s && echo OK"
|
|
% (RELAY_DIR, RELAY_DIR), timeout=120)
|
|
print(" " + out[1].strip())
|
|
|
|
cmd = (REMOTE.replace("__DIR__", RELAY_DIR)
|
|
.replace("__PORT__", PORT)
|
|
.replace("__PUBLIC__", PUBLIC))
|
|
out = run(cmd, timeout=300, quiet=True)
|
|
print(out[1] if isinstance(out, tuple) else out)
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|