阿克森雲登入 / 註冊English/中文/cn繁體/tw

mtr-report.py

AxionServe官方ai-code2026-10-01♥ 0
🤖 AIGC 披露:本作品由「AI 輔助生成 + 人工實測」輔助創作,經社區公約審核發布。
#!/usr/bin/env python3
# mtr-report.py (FIXED) — MTR 報告解析與存證(僅標準庫)
# 修復點(R7 審計 P1):
#   1) 原 NUM 正則不匹配真實 mtr 輸出:跳號後是 "N.|--"(點號後無空格、帶豎線),
#      原式要求 "\d+\.\s+--?" → 永遠 miss;且 Loss 列帶 "%",原式 ([\d.]+) 會喫掉 % 前的
#      數字後在 % 處斷掉 → 整行不匹配。
#   2) 刪除從未使用的 LINE 正則(死代碼,且本身括號不配對)。
#   3) 兼容 "???"(超時跳)主機名與反解主機名(-z 建議照舊)。
# 用法: mtr -rwzbc 100 目標IP > raw.txt && python3 mtr-report.py raw.txt 目標IP
import sys, re, json, datetime

NUM = re.compile(
    r"^\s*(\d+)\.\s*\|?--\s*"          # 跳號 + 可選豎線 + 雙橫線("1.|--" / "1. --")
    r"(\S+.*?)\s+"                      # 主機(含 "???")
    r"([\d.]+)%\s+"                     # Loss%(必須帶百分號)
    r"(\d+)\s+"                         # Snt
    r"([\d.]+)\s+([\d.]+)\s+([\d.]+)\s+([\d.]+)\s+([\d.]+)\s*$"  # Last Avg Best Wrst StDev
)

def parse(path):
    hops = []
    for ln in open(path, encoding="utf-8", errors="replace"):
        m = NUM.match(ln.rstrip())
        if not m:
            continue
        hops.append(dict(
            hop=int(m.group(1)), host=m.group(2).strip(),
            loss=float(m.group(3)), snt=int(m.group(4)),
            last=float(m.group(5)), avg=float(m.group(6)),
            best=float(m.group(7)), wrst=float(m.group(8)),
            stdev=float(m.group(9))))
    return hops

def judge(hops):
    flags = []
    last = hops[-1] if hops else None
    for h in hops:
        if h["loss"] > 0 and h is not last:
            after = [x for x in hops if x["hop"] > h["hop"]]
            if after and all(x["loss"] == 0 for x in after):
                flags.append((h["hop"], "ICMP_RATE_LIMITED",
                              "中間跳丟包且後續正常:疑似路由器限速 ICMP,非故障"))
        if h["avg"] > 0 and h["stdev"] > h["avg"] * 0.5:
            flags.append((h["hop"], "HIGH_JITTER",
                          f"StDev {h['stdev']} > Avg {h['avg']}×0.5:顯著抖動"))
    verdict = "PATH_OK"
    if last and last["loss"] > 0:
        verdict = "REAL_LOSS"
        flags.append((last["hop"], "REAL_LOSS",
                      f"末跳持續丟包 {last['loss']}%:真丟包,可開工單"))
    return verdict, flags

def main():
    if len(sys.argv) < 3:
        print(__doc__); sys.exit(1)
    src, target = sys.argv[1], sys.argv[2]
    out = sys.argv[3] if len(sys.argv) > 3 else "mtr-evidence"
    hops = parse(src)
    if not hops:
        print("未解析到任何跳(確認輸入是 mtr --report/-rwzbc 格式)"); sys.exit(2)
    verdict, flags = judge(hops)
    ts = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
    meta = dict(target=target, generated=ts, hops=len(hops),
                verdict=verdict, source_file=src)
    with open(f"{out}-{ts}.json", "w", encoding="utf-8") as f:
        json.dump(dict(meta=meta, hops=hops,
                       flags=[dict(hop=a, tag=b, note=c) for a, b, c in flags]),
                  f, ensure_ascii=False, indent=1)
    md = ["# MTR 存證檔案", "",
          f"- 目標: `{target}`  · 生成: {ts}  · 判讀: **{verdict}**", "",
          "| 跳 | 主機 | Loss% | Snt | Avg | Wrst | StDev |",
          "|---|---|---|---|---|---|---|"]
    for h in hops:
        md.append(f"| {h['hop']} | {h['host']} | {h['loss']} | {h['snt']} "
                  f"| {h['avg']} | {h['wrst']} | {h['stdev']} |")
    if flags:
        md += ["", "## 自動判讀"]
        md += [f"- 第 {a} 跳 [{b}] {c}" for a, b, c in flags]
    with open(f"{out}-{ts}.md", "w", encoding="utf-8") as f:
        f.write("\n".join(md) + "\n")
    print(f"verdict={verdict} · 已寫 {out}-{ts}.json / {out}-{ts}.md")

if __name__ == "__main__":
    main()

──────────────────────
【實測記錄·修復版】對 mtr -rwzbc 100 樣例輸出解析通過(6 跳、含 ??? 超時跳、100.0% 丟包行);REAL_LOSS / ICMP_RATE_LIMITED / HIGH_JITTER 判定經構造樣例驗證。
【修復說明】R7 審計發現原版正則與真實 mtr 輸出失配(跳號列爲 "N.|--" 且 Loss 列帶 %),已修正爲 \d+\.\s*\|?-- 與 ([\d.]+)% 捕獲,並刪除未使用的 LINE 死代碼。
【工單口徑】把 .md 檔案直接貼工單:結論行(verdict)+ 逐跳表 + 判讀。
【已知邊界】喫 -z(不反解)輸出最穩;帶反解建議 mtr --report-wide -z 重跑。
復現提示詞(全文)
寫一個 Python3 腳本 mtr-report.py:解析 mtr --report(或 mtr -rwzbc N)的文本輸出(HOST: 行格式:跳號 主機 loss% snt last avg best wrst stdev),輸出兩份文件——JSON(結構化每跳數據+元信息)與 Markdown 存證檔案(表格+自動判讀結論)。判讀規則:末跳 loss>0 標注 REAL_LOSS;中間跳丟包但後續跳正常標注 ICMP_RATE_LIMITED(疑似限速,非故障);stdev>avg*0.5 標注 HIGH_JITTER。命令行參數:輸入文件、目標名、可選 --out 前綴。僅用標準庫。
♥ 0 贊會員登入後可點贊幫助 TA舉報
相關作品cost-calc.js (FIXED)mtr-report.pyfirst-hour-init.sh