#!/bin/bash # 历史故障时间线分析:判断失败是不是集中在某个时段(运营商时段性抖动)。 # # 数据源(都是设备上现成的): # watchdog.log —— 它每 10 秒探一次公网,失败会写一行,带时间戳 # tunnel.log —— QUIC 实例的拨号/掉线事件 # tunnel-h2.log —— HTTP/2 实例的同类事件 set -u WD=/root/lanremote-relay/watchdog.log MAIN=/root/lanremote-relay/tunnel.log H2=/root/lanremote-relay/tunnel-h2.log RELAY=/root/lanremote-relay/relay.log echo "════════ 1. 数据覆盖范围 ════════" for f in "$WD" "$MAIN" "$H2" "$RELAY"; do [ -f "$f" ] || continue first=$(head -1 "$f" 2>/dev/null | cut -c1-19) last=$(tail -1 "$f" 2>/dev/null | cut -c1-19) printf " %-14s %8d 行 %s ~ %s\n" "$(basename "$f")" "$(wc -l < "$f")" "$first" "$last" done echo echo "════════ 2. watchdog 记录的公网故障,按小时分桶 ════════" echo " (watchdog 只在公网不通时记一行,所以这就是故障的原始时间线)" grep '公网不通' "$WD" 2>/dev/null \ | grep -oE '^\[[0-9-]+ [0-9]{2}' \ | sed 's/\[//' | sort | uniq -c | tail -30 | sed 's/^/ /' echo echo "════════ 3. 恢复事件(故障结束)按小时 ════════" grep '公网恢复' "$WD" 2>/dev/null \ | grep -oE '^\[[0-9-]+ [0-9]{2}' \ | sed 's/\[//' | sort | uniq -c | tail -30 | sed 's/^/ /' echo echo "════════ 4. 隧道重启事件(watchdog 触发的)════════" grep -E '重启隧道' "$WD" 2>/dev/null | tail -20 | sed 's/^/ /' echo echo "════════ 5. QUIC 拨号失败按小时分桶 ════════" grep 'Failed to dial' "$MAIN" 2>/dev/null \ | cut -c1-13 | sort | uniq -c | tail -24 | sed 's/^/ /' echo echo "════════ 6. HTTP/2 掉线按小时分桶 ════════" grep 'Lost connection' "$H2" 2>/dev/null \ | cut -c1-13 | sort | uniq -c | tail -24 | sed 's/^/ /' echo echo "════════ 7. 最长的一次连续故障(从 watchdog 日志推)════════" grep -nE '公网不通|公网恢复' "$WD" 2>/dev/null | tail -60 \ | sed 's/^/ /' echo echo "════════ 8. 中转自身有没有异常 ════════" echo " 中转日志里的错误:" grep -icE 'traceback|error|exception' "$RELAY" 2>/dev/null | sed 's/^/ 匹配行数: /' grep -iE 'traceback|error|exception' "$RELAY" 2>/dev/null | tail -8 | sed 's/^/ /' echo " 下载中断记录:" grep -c '下载中断' "$RELAY" 2>/dev/null | sed 's/^/ 次数: /'