mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 11:20:43 +00:00
阶段3 管理页 - 清掉全部深色主题残留(地址框 #0b1220、按钮悬停 #262c36、 删除按钮 #2d1214 等 11 处),现在 0 处深色 - 接口全部正常:health / downloads / netcheck 阶段4 局域网诊断 - 查清楚"电脑不在同一网络"是怎么回事:被控端是**对的** (lan_ips() 报 ['192.168.2.64', '169.254.83.107'],真实地址排第一), 是手表当时真不在 192.168.2.x —— 可能连了 5G 频段的另一个路由器,或开着移动数据 - 所以改了手表的提示:不再只说"不在同一网络", 而是把**双方地址都打出来**,用户一眼能看出是网段不同还是连错 WiFi - 端到端验证局域网路径:认证 1 ms,功能列表 207 项 阶段1 结论修正(一天内推翻自己两次,如实记录) - 第一次判断"优选 IP 无用":错。半小时内确实能避开超时 IP - 第二次固定优选 IP:也错。那些实测 138ms 的 IP 半小时后全不通了 —— Cloudflare anycast 可达性随运营商路由变化,固定 IP 等于钉死到会失效的地址 - 最终:不固定,靠 GeoDNS + cloudflared 重试 + ha-connections 2 冗余 - 撤销后立即变好:连接稳定 2 条、超时告警 0 次、设备侧延迟 4.40s -> 1.66s - **真正的瓶颈**:分段实测发现本机到 Cloudflare 的**裸 RTT 就 1439 ms**, 比经隧道的请求(1215 ms)还慢。说明瓶颈是这条网络的 4G 上行本身, 不是设备的隧道。公网侧已无优化空间。 - 局域网 118 ms vs 公网 1215 ms,快 10 倍 —— 这才是该走的路 阶段5 验收 - 全量回归 29 项全通过 - 设备侧验收 38 项全通过 - 成品:setup exe 14.37 MB / server zip / watch apk,已同步到设备下载区
118 lines
5.6 KiB
Bash
118 lines
5.6 KiB
Bash
#!/bin/bash
|
||
# 最终验收(修正版:单引号里不要转义双引号;grep -c 取第一行)
|
||
set -u
|
||
|
||
BASE=http://127.0.0.1:8080
|
||
PUB=https://relay.xxmxxs.top
|
||
KEY=$(cat /root/lanremote-relay/data/admin_key.txt 2>/dev/null)
|
||
pass=0; fail=0
|
||
|
||
ok() { pass=$((pass+1)); echo " ✓ $1"; }
|
||
bad() { fail=$((fail+1)); echo " ✗ $1"; }
|
||
code() { curl -s -o /dev/null -w '%{http_code}' --max-time 25 "$@"; }
|
||
# grep -c 有时会输出多行(多个文件时),统一取第一行
|
||
cnt() { grep -c "$1" "$2" 2>/dev/null | head -1 | tr -d '[:space:]'; }
|
||
|
||
echo "════════ 一、官网 ════════"
|
||
c=$(code "$BASE/")
|
||
[ "$c" = "200" ] && ok "首页 HTTP 200" || bad "首页 HTTP $c"
|
||
curl -s --max-time 20 "$BASE/" -o /tmp/s.html
|
||
size=$(wc -c < /tmp/s.html | tr -d ' ')
|
||
[ "$size" -gt 10000 ] && ok "页面 $size 字节(内容丰富)" || bad "页面只有 $size 字节"
|
||
|
||
check() {
|
||
if grep -q "$2" /tmp/s.html; then ok "$1"; else bad "$1"; fi
|
||
}
|
||
check "吸顶导航" 'nav-in'
|
||
check "Hero" 'hero'
|
||
check "功能网格" 'id="features"'
|
||
check "三步上手" 'id="how"'
|
||
check "下载区" 'id="download"'
|
||
check "FAQ" 'id="faq"'
|
||
check "页脚" 'foot-in'
|
||
check "版本徽章" 'badge'
|
||
|
||
[ "$(cnt 'class="feat"' /tmp/s.html)" = "9" ] && ok "9 张功能卡" \
|
||
|| bad "功能卡 $(cnt 'class="feat"' /tmp/s.html) 张"
|
||
[ "$(cnt '<details class="faq"' /tmp/s.html)" = "6" ] && ok "6 条 FAQ" \
|
||
|| bad "FAQ $(cnt '<details class="faq"' /tmp/s.html) 条"
|
||
[ "$(cnt 'class="dl-card"' /tmp/s.html)" = "3" ] && ok "3 张下载卡" \
|
||
|| bad "下载卡 $(cnt 'class="dl-card"' /tmp/s.html) 张"
|
||
[ "$(cnt '管理入口' /tmp/s.html)" = "0" ] && ok "没有管理入口" || bad "还有管理入口"
|
||
[ "$(cnt 'src="/favicon.ico" alt=""' /tmp/s.html)" = "0" ] && ok "没有破图 logo" \
|
||
|| bad "还有破图"
|
||
[ "$(cnt '<svg' /tmp/s.html)" -ge 11 ] && ok "图标齐全($(cnt '<svg' /tmp/s.html) 个)" \
|
||
|| bad "图标只有 $(cnt '<svg' /tmp/s.html) 个"
|
||
|
||
echo
|
||
echo "════════ 二、管理页 ════════"
|
||
c=$(code -H "X-Admin: $KEY" "$BASE/zhongzhuanzhan")
|
||
[ "$c" = "200" ] && ok "登录后 HTTP 200" || bad "HTTP $c"
|
||
curl -s --max-time 20 -H "X-Admin: $KEY" "$BASE/zhongzhuanzhan" -o /tmp/a.html
|
||
[ "$(cnt 'dlPanel' /tmp/a.html)" -gt 0 ] && ok "下载区在" || bad "下载区丢了"
|
||
[ "$(cnt '网络体检' /tmp/a.html)" -gt 0 ] && ok "网络体检在" || bad "网络体检丢了"
|
||
[ "$(cnt '退出登录' /tmp/a.html)" -gt 0 ] && ok "退出登录在" || bad "退出登录丢了"
|
||
dark=0
|
||
for cc in 0b1220 262c36 1b222c 1c2733 2d1214 4a1a1e 484f58 0d1117; do
|
||
n=$(cnt "#$cc" /tmp/a.html)
|
||
[ -n "$n" ] && [ "$n" != "0" ] && dark=$((dark + n))
|
||
done
|
||
[ "$dark" = "0" ] && ok "无深色残留" || bad "深色残留 $dark 处"
|
||
[ "$(code "$BASE/admin")" = "302" ] && ok "/admin 跳转正常" || bad "/admin 跳转异常"
|
||
[ "$(code "$BASE/zhongzhuanzhan")" = "200" ] && ok "未登录看到登录页" || bad "未登录页异常"
|
||
|
||
echo
|
||
echo "════════ 三、下载 ════════"
|
||
for f in ykxmz-setup-1.7.1.exe ykxmz-server-1.7.1.zip ykxmz-watch-1.7.1.apk; do
|
||
c=$(code "$BASE/download/$f")
|
||
[ "$c" = "200" ] && ok "$f" || bad "$f HTTP $c"
|
||
done
|
||
[ "$(code "$BASE/v1/downloads")" = "200" ] && ok "/v1/downloads" || bad "/v1/downloads"
|
||
tc=$(code "$BASE/download/../relay.py")
|
||
{ [ "$tc" = "404" ] || [ "$tc" = "400" ]; } && ok "路径穿越被挡($tc)" \
|
||
|| bad "路径穿越 HTTP $tc"
|
||
|
||
echo
|
||
echo "════════ 四、加速 ════════"
|
||
proto=$(grep -oE 'Initial protocol [a-z0-9]+' /root/lanremote-relay/tunnel.log 2>/dev/null | tail -1)
|
||
echo "$proto" | grep -q http2 && ok "隧道走 HTTP/2(不是 QUIC)" || bad "隧道协议: $proto"
|
||
conn=$(curl -s --max-time 5 http://127.0.0.1:20241/metrics 2>/dev/null \
|
||
| grep '^cloudflared_tunnel_ha_connections' | awk '{print $2}' | head -1)
|
||
[ "$conn" = "2" ] && ok "隧道连接数 2" || echo " · 隧道连接数 $conn(1 也可用,2 才有冗余)"
|
||
[ "$(sysctl -n net.ipv4.tcp_mtu_probing)" = "1" ] && ok "MTU 探测开着" || bad "MTU 探测关了"
|
||
[ "$(sysctl -n net.ipv4.tcp_slow_start_after_idle)" = "0" ] && ok "空闲后不重置窗口" \
|
||
|| bad "slow_start 没关"
|
||
[ "$(sysctl -n net.ipv4.tcp_fastopen)" = "3" ] && ok "TCP FastOpen 开着" || bad "FastOpen 没开"
|
||
[ "$(cnt argotunnel /etc/hosts)" = "0" ] && ok "无效的 hosts 覆盖已清" || bad "hosts 有残留"
|
||
|
||
echo
|
||
echo "════════ 五、功能 ════════"
|
||
for api in /v1/health /favicon.ico; do
|
||
c=$(code "$BASE$api")
|
||
[ "$c" = "200" ] && ok "$api" || bad "$api HTTP $c"
|
||
done
|
||
curl -s --max-time 10 "$BASE/v1/health" | grep -o '"version": *"[^"]*"' | sed 's/^/ /'
|
||
|
||
echo
|
||
echo "════════ 六、公网可用性(设备侧,发夹回路=最坏情况)════════"
|
||
okc=0; total=0
|
||
for i in $(seq 1 15); do
|
||
r=$(curl -s -o /dev/null -w '%{http_code} %{time_total}' --max-time 25 \
|
||
-H 'User-Agent: LanRemote/1.4.0' "$PUB/" 2>/dev/null)
|
||
c=$(echo "$r" | cut -d' ' -f1)
|
||
t=$(echo "$r" | cut -d' ' -f2)
|
||
if [ "$c" = "200" ]; then
|
||
okc=$((okc+1))
|
||
total=$(echo "$total + $t" | bc)
|
||
fi
|
||
sleep 0.5
|
||
done
|
||
avg=$(echo "scale=2; $total / $okc" | bc 2>/dev/null || echo "?")
|
||
[ "$okc" -ge 14 ] && ok "可用 $okc/15" || bad "可用 $okc/15"
|
||
echo " 平均 ${avg} 秒(真实用户路径比这个快,见 Windows 侧实测)"
|
||
|
||
echo
|
||
echo "════════════════════════════════"
|
||
echo " 通过 $pass 项,失败 $fail 项"
|
||
[ "$fail" = "0" ] && echo " 全部通过 ✓" || echo " 有失败"
|