#!/bin/bash # 分析 relay-stability 的 2 小时健康长测数据(只读) set -u F=/root/long2h_health.tsv [ -f "$F" ] || { echo " 数据文件不存在: $F"; exit 0; } echo " 文件: $F 行数: $(wc -l < "$F")" echo " 前 3 行(看格式):" head -3 "$F" | sed 's/^/ /' echo python3 - "$F" <<'PYEOF' import sys from collections import Counter from pathlib import Path path = Path(sys.argv[1]) lines = [l.strip() for l in path.read_text(encoding="utf-8", errors="replace").splitlines() if l.strip()] if not lines: print(" 没有数据") raise SystemExit(0) # 猜列:先看表头,没有表头就按 tab 切 head = lines[0].lower() has_header = any(k in head for k in ("time", "code", "ms", "http")) rows = lines[1:] if has_header else lines if has_header: print(" 表头: %s" % lines[0]) print(" 样本数: %d" % len(rows)) codes = Counter() times = [] conns = [] fails = [] for i, line in enumerate(rows, 1): parts = line.split("\t") code = None ms = None for p in parts: p = p.strip() if p.isdigit() and len(p) == 3: code = p if p.replace(".", "").isdigit() and "." in p: try: v = float(p) if ms is None and v < 300000: ms = v except ValueError: pass if code: codes[code] += 1 if code != "200": fails.append((i, line[:100])) if ms: times.append(ms) # 连接数:找形如 quic=N h2=M 或者单独的数字 for p in parts: if "quic=" in p: conns.append(p.strip()) total = sum(codes.values()) ok = codes.get("200", 0) print() print(" ── HTTP 结果分布 ──") for c, n in codes.most_common(): pct = n * 100.0 / total if total else 0 print(" %-6s %4d 次 %.1f%%" % (c, n, pct)) print(" --------") print(" 可用率: %d/%d = %.1f%%" % (ok, total, ok * 100.0 / total if total else 0)) if times: s = sorted(times) def pct(q): return s[min(int(len(s) * q), len(s) - 1)] print() print(" ── 耗时分布(毫秒)──") print(" 最小 %.0f 中位 %.0f P90 %.0f P99 %.0f 最大 %.0f" % (s[0], s[len(s)//2], pct(0.9), pct(0.99), s[-1])) if conns: c = Counter(conns) print() print(" ── 连接数分布(前 8)──") for k, n in c.most_common(8): print(" %-28s %d 次" % (k, n)) if fails: print() print(" ── 失败样本(最多 12 条)──") for i, line in fails[:12]: print(" 第 %d 行: %s" % (i, line)) else: print() print(" ✓ 全程没有非 200") PYEOF