Upload files to "/"

This commit is contained in:
mike 2026-05-09 15:14:41 +08:00
parent d783090418
commit a308d17b60
1 changed files with 482 additions and 0 deletions

482
route_test.sh Normal file
View File

@ -0,0 +1,482 @@
#!/bin/bash
# ============================================================
# 三网路由检测脚本 (电信 / 联通 / 移动)
# 适用系统: Debian / Ubuntu
# 功能: 自动安装依赖,测试去程+回程路由
# ============================================================
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BOLD='\033[1m'
RESET='\033[0m'
# ── 测试目标 IP ──────────────────────────────────────────────
# 去程从本地到这些国内IP
TELECOM_IPS=("202.96.209.5" "61.139.2.69" "211.137.58.20") # 电信各省
UNICOM_IPS=("211.95.46.3" "218.104.111.114" "61.135.169.121") # 联通各省
MOBILE_IPS=("221.179.131.11" "223.5.5.5" "120.196.165.1") # 移动各省
# 回程测试目标
TELECOM_RETURN="180.97.33.108" # 电信上海
UNICOM_RETURN="218.104.111.114" # 联通武汉
MOBILE_RETURN="221.179.131.11" # 移动北京
# ── 辅助函数 ─────────────────────────────────────────────────
print_banner() {
echo -e "${CYAN}"
echo "╔══════════════════════════════════════════════════╗"
echo "║ 三网路由检测脚本 by route_test ║"
echo "║ 电信 / 联通 / 移动 去程 + 回程 ║"
echo "╚══════════════════════════════════════════════════╝"
echo -e "${RESET}"
}
print_section() {
echo ""
echo -e "${BOLD}${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}"
echo -e "${BOLD}${YELLOW} $1${RESET}"
echo -e "${BOLD}${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}"
}
check_root() {
if [[ $EUID -ne 0 ]]; then
echo -e "${RED}[错误] 请使用 root 用户运行此脚本${RESET}"
echo " sudo bash route_test.sh"
exit 1
fi
}
get_vps_info() {
print_section "📋 VPS 基本信息"
local ip=$(curl -s --max-time 5 ip.sb 2>/dev/null || echo "获取失败")
local info=$(curl -s --max-time 5 ipinfo.io 2>/dev/null)
local org=$(echo "$info" | grep '"org"' | cut -d'"' -f4)
local city=$(echo "$info" | grep '"city"' | cut -d'"' -f4)
local country=$(echo "$info" | grep '"country"' | cut -d'"' -f4)
echo -e " IP地址 : ${GREEN}${ip}${RESET}"
echo -e " 归属地 : ${GREEN}${country} ${city}${RESET}"
echo -e " ASN/运营: ${GREEN}${org}${RESET}"
echo -e " 系统 : ${GREEN}$(lsb_release -d 2>/dev/null | cut -f2)${RESET}"
echo -e " 内核 : ${GREEN}$(uname -r)${RESET}"
echo -e " 时间 : ${GREEN}$(date '+%Y-%m-%d %H:%M:%S %Z')${RESET}"
}
install_deps() {
print_section "🔧 检查并安装依赖"
# ── 检测系统架构 ──────────────────────────────────────────
local arch_raw
arch_raw=$(uname -m)
local nt_arch=""
case "$arch_raw" in
x86_64) nt_arch="amd64" ;;
aarch64|arm64) nt_arch="arm64" ;;
armv7l|armv6l) nt_arch="armv7" ;;
mips) nt_arch="mips" ;;
mips64) nt_arch="mips64";;
mipsle|mipsel) nt_arch="mipsle";;
*) nt_arch="" ;;
esac
echo -e " 系统架构: ${GREEN}${arch_raw}${RESET} → nexttrace 目标包: ${GREEN}${nt_arch:-不支持}${RESET}"
apt-get update -qq 2>/dev/null
# mtr
if ! command -v mtr &>/dev/null; then
echo -e " ${YELLOW}安装 mtr...${RESET}"
apt-get install -y -qq mtr-tiny 2>/dev/null && \
echo -e " ${GREEN}✔ mtr 安装完成${RESET}" || \
echo -e " ${RED}✘ mtr 安装失败${RESET}"
else
echo -e " ${GREEN}✔ mtr 已安装${RESET}"
fi
# traceroute
if ! command -v traceroute &>/dev/null; then
echo -e " ${YELLOW}安装 traceroute...${RESET}"
apt-get install -y -qq traceroute 2>/dev/null && \
echo -e " ${GREEN}✔ traceroute 安装完成${RESET}" || \
echo -e " ${RED}✘ traceroute 安装失败${RESET}"
else
echo -e " ${GREEN}✔ traceroute 已安装${RESET}"
fi
# nexttrace
if command -v nexttrace &>/dev/null; then
echo -e " ${GREEN}✔ nexttrace 已安装 $(nexttrace --version 2>/dev/null | head -1)${RESET}"
return
fi
if [[ -z "$nt_arch" ]]; then
echo -e " ${RED}✘ 不支持的架构 (${arch_raw}),跳过 nexttrace 安装${RESET}"
return
fi
echo -e " ${YELLOW}安装 nexttrace (${nt_arch})...${RESET}"
local nt_bin="/usr/local/bin/nexttrace"
local nt_file="nexttrace_linux_${nt_arch}"
local gh_url="https://github.com/nxtrace/NTrace-core/releases/latest/download/${nt_file}"
local mirror_url="https://ghfast.top/${gh_url}"
# 依次尝试: 官方安装脚本 → GitHub 直链 → ghfast 镜像
local installed=0
# 方法1: 官方安装脚本
echo -e " ${CYAN}[1/3] 尝试官方安装脚本...${RESET}"
if curl -sf --max-time 15 https://raw.githubusercontent.com/nxtrace/NTrace-core/main/nt_install.sh \
| bash -s -- --yes &>/dev/null; then
command -v nexttrace &>/dev/null && installed=1
fi
# 方法2: GitHub Releases 直链
if [[ $installed -eq 0 ]]; then
echo -e " ${CYAN}[2/3] 尝试 GitHub 直链下载...${RESET}"
if curl -fL --max-time 30 -o "$nt_bin" "$gh_url" 2>/dev/null; then
chmod +x "$nt_bin"
command -v nexttrace &>/dev/null && installed=1
fi
fi
# 方法3: ghfast 镜像
if [[ $installed -eq 0 ]]; then
echo -e " ${CYAN}[3/3] 尝试 ghfast 镜像下载...${RESET}"
if curl -fL --max-time 30 -o "$nt_bin" "$mirror_url" 2>/dev/null; then
chmod +x "$nt_bin"
command -v nexttrace &>/dev/null && installed=1
fi
fi
if [[ $installed -eq 1 ]]; then
echo -e " ${GREEN}✔ nexttrace 安装完成 $(nexttrace --version 2>/dev/null | head -1)${RESET}"
else
echo -e " ${RED}✘ nexttrace 全部安装方式失败,回程追踪将降级为 traceroute${RESET}"
echo -e " ${YELLOW} 手动安装: curl -Lo ${nt_bin} ${mirror_url} && chmod +x ${nt_bin}${RESET}"
fi
}
# ── 全局结果收集变量 ─────────────────────────────────────────
# 延迟(ms): -1 = 超时
TELECOM_AVG_LATENCY=-1
UNICOM_AVG_LATENCY=-1
MOBILE_AVG_LATENCY=-1
# 回程线路识别: unknown / cn2 / 163 / 9929 / 4837 / cmin2 / cmnet / mixed
TELECOM_RETURN_LINE="unknown"
UNICOM_RETURN_LINE="unknown"
MOBILE_RETURN_LINE="unknown"
# MTR 最终跳丢包率(%)
TELECOM_LOSS=-1
UNICOM_LOSS=-1
MOBILE_LOSS=-1
# ── 去程测试ping延迟────────────────────────────────────────
ping_test() {
local ip=$1
local result
result=$(ping -c 3 -W 3 "$ip" 2>/dev/null | tail -1 | awk -F'/' '{print $5}')
if [[ -n "$result" ]]; then
echo -e " ${ip}${GREEN}${result} ms${RESET}"
echo "$result" # 供调用方捕获
else
echo -e " ${ip}${RED}超时/不可达${RESET}"
echo "-1"
fi
}
# 计算一组 IP 的平均延迟(忽略超时)
avg_latency_for() {
local -n _ips=$1
local total=0 count=0
for ip in "${_ips[@]}"; do
local val
val=$(ping -c 3 -W 3 "$ip" 2>/dev/null | tail -1 | awk -F'/' '{print $5}')
if [[ -n "$val" && "$val" != "-1" ]]; then
total=$(awk "BEGIN{print $total + $val}")
((count++))
fi
done
if [[ $count -gt 0 ]]; then
awk "BEGIN{printf \"%.1f\", $total / $count}"
else
echo "-1"
fi
}
outbound_test() {
print_section "📤 去程延迟测试VPS → 国内)"
echo -e "\n ${BOLD}▶ 电信${RESET}"
for ip in "${TELECOM_IPS[@]}"; do ping_test "$ip" > /dev/null; done
# 单独计算平均值供评估用(不重复输出)
for ip in "${TELECOM_IPS[@]}"; do
local r; r=$(ping -c 3 -W 3 "$ip" 2>/dev/null | tail -1 | awk -F'/' '{print $5}')
[[ -n "$r" ]] && echo -e " ${ip}${GREEN}${r} ms${RESET}" || echo -e " ${ip}${RED}超时/不可达${RESET}"
done
TELECOM_AVG_LATENCY=$(avg_latency_for TELECOM_IPS)
echo -e "\n ${BOLD}▶ 联通${RESET}"
for ip in "${UNICOM_IPS[@]}"; do
local r; r=$(ping -c 3 -W 3 "$ip" 2>/dev/null | tail -1 | awk -F'/' '{print $5}')
[[ -n "$r" ]] && echo -e " ${ip}${GREEN}${r} ms${RESET}" || echo -e " ${ip}${RED}超时/不可达${RESET}"
done
UNICOM_AVG_LATENCY=$(avg_latency_for UNICOM_IPS)
echo -e "\n ${BOLD}▶ 移动${RESET}"
for ip in "${MOBILE_IPS[@]}"; do
local r; r=$(ping -c 3 -W 3 "$ip" 2>/dev/null | tail -1 | awk -F'/' '{print $5}')
[[ -n "$r" ]] && echo -e " ${ip}${GREEN}${r} ms${RESET}" || echo -e " ${ip}${RED}超时/不可达${RESET}"
done
MOBILE_AVG_LATENCY=$(avg_latency_for MOBILE_IPS)
}
# ── 回程路由追踪 + 线路识别 ───────────────────────────────────
# 返回识别到的线路标签,写入全局变量 _DETECTED_LINE
_DETECTED_LINE="unknown"
detect_line_from_trace() {
local trace_output="$1"
local lower
lower=$(echo "$trace_output" | tr '[:upper:]' '[:lower:]')
if echo "$lower" | grep -qE 'as4809|cn2|cnc-gia'; then
_DETECTED_LINE="cn2"
elif echo "$lower" | grep -qE 'as58807|cmin2'; then
_DETECTED_LINE="cmin2"
elif echo "$lower" | grep -qE 'as9929|cnc-backbone|cuii'; then
_DETECTED_LINE="9929"
elif echo "$lower" | grep -qE 'as4837|cu169|169骨干'; then
_DETECTED_LINE="4837"
elif echo "$lower" | grep -qE 'as9808|cmnet'; then
_DETECTED_LINE="cmnet"
elif echo "$lower" | grep -qE 'as4134|chinanet|163骨干'; then
_DETECTED_LINE="163"
else
_DETECTED_LINE="unknown"
fi
}
return_route_nexttrace() {
local label=$1
local ip=$2
local color=$3
local result_var=$4 # 写回哪个全局变量
echo -e "\n ${color}${BOLD}${label} 回程路由 → ${ip}${RESET}"
echo -e " ${CYAN}$(printf '─%.0s' {1..48})${RESET}"
local trace_output=""
if command -v nexttrace &>/dev/null; then
trace_output=$(nexttrace --no-rdns "$ip" 2>/dev/null)
echo "$trace_output" | grep -v "^$" | sed 's/^/ /'
else
echo -e " ${RED}nexttrace 未安装,使用 traceroute 替代无ASN信息${RESET}"
trace_output=$(traceroute -n -m 20 "$ip" 2>/dev/null)
echo "$trace_output" | sed 's/^/ /'
fi
detect_line_from_trace "$trace_output"
eval "$result_var=\"$_DETECTED_LINE\""
}
return_route_test() {
print_section "📥 回程路由追踪VPS → 国内三网)"
echo -e " ${YELLOW}提示: 关注 AS 号码${RESET}"
echo -e " ${YELLOW} 电信CN2: as4809 普通163: as4134${RESET}"
echo -e " ${YELLOW} 联通9929: as9929 普通169: as4837${RESET}"
echo -e " ${YELLOW} 移动CMIN2: as58807 普通CMNet: as9808${RESET}"
return_route_nexttrace "电信" "$TELECOM_RETURN" "$RED" "TELECOM_RETURN_LINE"
return_route_nexttrace "联通" "$UNICOM_RETURN" "$BLUE" "UNICOM_RETURN_LINE"
return_route_nexttrace "移动" "$MOBILE_RETURN" "$GREEN" "MOBILE_RETURN_LINE"
}
# ── MTR 质量测试 ──────────────────────────────────────────────
mtr_test() {
print_section "📊 MTR 丢包率测试各发送10个包"
_run_mtr() {
local label=$1 ip=$2 loss_var=$3
echo -e "\n ${BOLD}${label} (${ip})${RESET}"
if command -v mtr &>/dev/null; then
local mtr_out
mtr_out=$(mtr --report --report-cycles 10 --no-dns "$ip" 2>/dev/null)
echo "$mtr_out" | awk 'NR>1 {printf " %-5s %-18s Loss:%5s Avg:%7s ms\n", $1, $2, $3, $8}' | head -20
# 取最后一个有效跳的丢包率
local loss
loss=$(echo "$mtr_out" | awk 'NR>1 && $2!="???" {last=$3} END{print last}' | tr -d '%')
eval "$loss_var=\"${loss:--1}\""
else
echo -e " ${RED}mtr 未安装${RESET}"
fi
}
_run_mtr "电信上海" "$TELECOM_RETURN" "TELECOM_LOSS"
_run_mtr "联通武汉" "$UNICOM_RETURN" "UNICOM_LOSS"
_run_mtr "移动北京" "$MOBILE_RETURN" "MOBILE_LOSS"
}
# ── 线路评级 ─────────────────────────────────────────────────
# 入参: 线路标签字符串,返回评分 0~5 和颜色
rate_line() {
local line=$1
case "$line" in
cn2) echo "5|${GREEN}|CN2/GIA ⭐⭐⭐⭐⭐ 顶级优化线路" ;;
9929) echo "4|${GREEN}|AS9929 ⭐⭐⭐⭐ 联通精品线路" ;;
cmin2) echo "4|${GREEN}|CMIN2 ⭐⭐⭐⭐ 移动精品线路" ;;
4837) echo "2|${YELLOW}|AS4837 ⭐⭐ 联通普通169骨干" ;;
cmnet) echo "2|${YELLOW}|CMNet ⭐⭐ 移动普通骨干" ;;
163) echo "1|${YELLOW}|AS4134 ⭐ 电信普通163骨干" ;;
unknown) echo "0|${RED}|未识别 ❓ 无法判断线路质量" ;;
*) echo "0|${RED}|未知 ❓ 无法判断线路质量" ;;
esac
}
# 延迟评级
rate_latency() {
local ms=$1
if [[ "$ms" == "-1" ]]; then
echo "${RED}超时/全部不可达"
elif awk "BEGIN{exit !($ms < 150)}"; then
echo "${GREEN}${ms} ms 极佳 (<150ms)"
elif awk "BEGIN{exit !($ms < 200)}"; then
echo "${GREEN}${ms} ms 良好 (<200ms)"
elif awk "BEGIN{exit !($ms < 250)}"; then
echo "${YELLOW}${ms} ms 一般 (<250ms)"
else
echo "${RED}${ms} ms 较差 (>250ms)"
fi
}
# 丢包评级
rate_loss() {
local loss=$1
if [[ "$loss" == "-1" ]]; then
echo "${YELLOW}未测试"
elif awk "BEGIN{exit !($loss == 0)}"; then
echo "${GREEN}0% 无丢包"
elif awk "BEGIN{exit !($loss <= 2)}"; then
echo "${GREEN}${loss}% 正常"
elif awk "BEGIN{exit !($loss <= 5)}"; then
echo "${YELLOW}${loss}% 轻微丢包"
elif awk "BEGIN{exit !($loss <= 15)}"; then
echo "${RED}${loss}% 丢包明显"
else
echo "${RED}${loss}% 丢包严重"
fi
}
# ── 综合评估 ─────────────────────────────────────────────────
evaluate() {
print_section "📊 综合评估报告"
local isp_names=("电信" "联通" "移动")
local return_lines=("$TELECOM_RETURN_LINE" "$UNICOM_RETURN_LINE" "$MOBILE_RETURN_LINE")
local latencies=("$TELECOM_AVG_LATENCY" "$UNICOM_AVG_LATENCY" "$MOBILE_AVG_LATENCY")
local losses=("$TELECOM_LOSS" "$UNICOM_LOSS" "$MOBILE_LOSS")
local colors=("$RED" "$BLUE" "$GREEN")
local total_score=0
local scored_count=0
printf "\n %-6s %-28s %-22s %-14s\n" "运营商" "回程线路" "去程延迟" "丢包率"
echo -e " ${BLUE}$(printf '─%.0s' {1..75})${RESET}"
for i in 0 1 2; do
local isp="${isp_names[$i]}"
local line="${return_lines[$i]}"
local lat="${latencies[$i]}"
local loss="${losses[$i]}"
local color="${colors[$i]}"
local rate_info; rate_info=$(rate_line "$line")
local score="${rate_info%%|*}"
local line_color; line_color=$(echo "$rate_info" | cut -d'|' -f2)
local line_label; line_label=$(echo "$rate_info" | cut -d'|' -f3)
local lat_str; lat_str=$(rate_latency "$lat")
local loss_str; loss_str=$(rate_loss "$loss")
printf " ${color}${BOLD}%-6s${RESET} ${line_color}%-28s${RESET} ${lat_str}%-0s${RESET} ${loss_str}%-0s${RESET}\n" \
"$isp" "$line_label" "" ""
if [[ "$score" -gt 0 ]]; then
total_score=$((total_score + score))
((scored_count++))
fi
done
echo -e " ${BLUE}$(printf '─%.0s' {1..75})${RESET}"
# ── 总体评语 ──────────────────────────────────────────────
echo ""
local avg_score=0
[[ $scored_count -gt 0 ]] && avg_score=$((total_score / scored_count))
local verdict=""
local verdict_color=""
if [[ $avg_score -ge 4 ]]; then
verdict_color="${GREEN}"
verdict="优质线路,三网均走精品通道,适合对延迟敏感的业务(游戏/直播/企业)"
elif [[ $avg_score -eq 3 ]]; then
verdict_color="${GREEN}"
verdict="良好线路,部分运营商走优化通道,日常使用体验较好"
elif [[ $avg_score -eq 2 ]]; then
verdict_color="${YELLOW}"
verdict="普通线路,走普通骨干网,延迟和稳定性一般,适合轻度使用"
elif [[ $avg_score -eq 1 ]]; then
verdict_color="${YELLOW}"
verdict="较差线路,高峰期可能拥堵,建议评估是否符合使用需求"
else
verdict_color="${RED}"
verdict="线路质量未知或较差,建议进一步测试或联系商家确认"
fi
echo -e " ${BOLD}总体评价: ${verdict_color}${verdict}${RESET}"
# ── 分运营商建议 ──────────────────────────────────────────
echo ""
echo -e " ${BOLD}分运营商建议:${RESET}"
for i in 0 1 2; do
local isp="${isp_names[$i]}"
local line="${return_lines[$i]}"
local lat="${latencies[$i]}"
local tip=""
case "$line" in
cn2|9929|cmin2)
tip="✅ 线路优质,推荐使用"
[[ $(awk "BEGIN{print ($lat > 0 && $lat > 220)}") == "1" ]] && \
tip="${tip}(延迟略高,属正常范围)"
;;
4837|cmnet|163)
tip="⚠️ 普通骨干线路,高峰期可能拥堵,敏感业务慎用"
;;
unknown)
tip="❓ 线路未能识别,建议手动查看回程路由中的 AS 号"
;;
esac
echo -e " ${colors[$i]}${isp}${RESET}: ${tip}"
done
echo ""
echo -e " ${CYAN}如需可视化路由图,访问 nexttrace 输出的 MapTrace URL${RESET}"
echo -e " ${CYAN}如需重新测试: bash route_test.sh${RESET}"
echo ""
}
# ── 主流程 ────────────────────────────────────────────────────
main() {
check_root
print_banner
get_vps_info
install_deps
outbound_test
return_route_test
mtr_test
evaluate
}
main