136 lines
3.9 KiB
Bash
Executable File
136 lines
3.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
set -euo pipefail
|
||
|
||
# PMFlow 公网穿透启动器(保留为唯一 tunnel 入口)
|
||
# 优先命名隧道;未配置时自动退回 quick tunnel。
|
||
|
||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||
ROOT_DIR="$(cd -- "${SCRIPT_DIR}/../.." && pwd)"
|
||
CONFIG_FILE="${SCRIPT_DIR}/config.yml"
|
||
SETUP_SCRIPT="${SCRIPT_DIR}/setup.sh"
|
||
LOG_DIR="${ROOT_DIR}/logs"
|
||
|
||
FRONTEND_PORT="${PMFLOW_TUNNEL_FRONTEND_PORT:-${FRONTEND_PORT:-5174}}"
|
||
BACKEND_PORT="${PMFLOW_TUNNEL_BACKEND_PORT:-${BACKEND_PORT:-8000}}"
|
||
TUNNEL_PROTOCOL="${PMFLOW_TUNNEL_PROTOCOL:-quic}"
|
||
HEALTH_RETRIES="${PMFLOW_TUNNEL_HEALTH_RETRIES:-3}"
|
||
FOREGROUND="${PMFLOW_TUNNEL_FOREGROUND:-1}"
|
||
|
||
FRONT_LOG="${LOG_DIR}/tunnel-frontend.log"
|
||
BACK_LOG="${LOG_DIR}/tunnel-backend.log"
|
||
|
||
extract_url() {
|
||
local logfile="$1"
|
||
grep -aEo 'https://[-a-z0-9]+\.trycloudflare\.com' "$logfile" 2>/dev/null | tail -1
|
||
}
|
||
|
||
wait_for_url() {
|
||
local logfile="$1"
|
||
local retries="${2:-30}"
|
||
local i=1
|
||
local url=""
|
||
while [ "$i" -le "$retries" ]; do
|
||
url="$(extract_url "$logfile")"
|
||
if [ -n "$url" ]; then
|
||
echo "$url"
|
||
return 0
|
||
fi
|
||
sleep 1
|
||
i=$((i + 1))
|
||
done
|
||
return 1
|
||
}
|
||
|
||
check_url() {
|
||
local url="$1"
|
||
local max_retry="$2"
|
||
local retry=1
|
||
while [ "$retry" -le "$max_retry" ]; do
|
||
if curl -kfsS --max-time 8 "$url" >/dev/null 2>&1; then
|
||
return 0
|
||
fi
|
||
sleep 2
|
||
retry=$((retry + 1))
|
||
done
|
||
return 1
|
||
}
|
||
|
||
run_quick_tunnels() {
|
||
mkdir -p "$LOG_DIR"
|
||
pkill -f "cloudflared tunnel .*127\\.0\\.0\\.1:${FRONTEND_PORT}" >/dev/null 2>&1 || true
|
||
pkill -f "cloudflared tunnel .*127\\.0\\.0\\.1:${BACKEND_PORT}" >/dev/null 2>&1 || true
|
||
|
||
echo "🚀 启动临时隧道..."
|
||
echo "📂 日志目录: ${LOG_DIR}"
|
||
echo "🌐 前端隧道: 127.0.0.1:${FRONTEND_PORT}"
|
||
cloudflared tunnel --protocol "${TUNNEL_PROTOCOL}" --url "http://127.0.0.1:${FRONTEND_PORT}" >"$FRONT_LOG" 2>&1 &
|
||
local front_pid=$!
|
||
|
||
echo "🌐 后端隧道: 127.0.0.1:${BACKEND_PORT}"
|
||
cloudflared tunnel --protocol "${TUNNEL_PROTOCOL}" --url "http://127.0.0.1:${BACKEND_PORT}" >"$BACK_LOG" 2>&1 &
|
||
local back_pid=$!
|
||
|
||
echo "⏳ 等待隧道地址..."
|
||
local front_url=""
|
||
local back_url=""
|
||
front_url="$(wait_for_url "$FRONT_LOG" 45 || true)"
|
||
back_url="$(wait_for_url "$BACK_LOG" 45 || true)"
|
||
|
||
if [ -z "$front_url" ] || [ -z "$back_url" ]; then
|
||
echo "❌ 未获取到公网地址。"
|
||
echo " 前端日志: $FRONT_LOG"
|
||
echo " 后端日志: $BACK_LOG"
|
||
tail -n 20 "$FRONT_LOG" || true
|
||
tail -n 20 "$BACK_LOG" || true
|
||
kill "$front_pid" "$back_pid" >/dev/null 2>&1 || true
|
||
return 1
|
||
fi
|
||
|
||
local front_ok=false
|
||
local back_ok=false
|
||
if check_url "${front_url}/login" "$HEALTH_RETRIES" || check_url "${front_url}" "$HEALTH_RETRIES"; then
|
||
front_ok=true
|
||
fi
|
||
if check_url "${back_url}/healthz" "$HEALTH_RETRIES"; then
|
||
back_ok=true
|
||
fi
|
||
|
||
if [ "$front_ok" = true ] && [ "$back_ok" = true ]; then
|
||
echo "✅ 隧道连通成功"
|
||
else
|
||
echo "⚠️ 隧道已启动,但健康检查未全部通过(可稍后重试)"
|
||
fi
|
||
|
||
echo "----------------------------------------"
|
||
echo "前端: ${front_url}"
|
||
echo "后端: ${back_url}"
|
||
echo "----------------------------------------"
|
||
echo "ℹ️ 停止命令: pkill -f \"cloudflared tunnel\""
|
||
|
||
if [ "$FOREGROUND" != "1" ]; then
|
||
echo "✅ 已切到后台运行"
|
||
echo " 前端 PID: ${front_pid}"
|
||
echo " 后端 PID: ${back_pid}"
|
||
return 0
|
||
fi
|
||
|
||
cleanup() {
|
||
echo ""
|
||
echo "🔴 tunnel 已关闭"
|
||
kill "$front_pid" "$back_pid" >/dev/null 2>&1 || true
|
||
}
|
||
trap cleanup EXIT INT TERM
|
||
wait "$front_pid" "$back_pid"
|
||
}
|
||
|
||
echo "🚀 启动公网穿透..."
|
||
if [ -f "$CONFIG_FILE" ]; then
|
||
echo "✅ 检测到命名隧道配置: ${CONFIG_FILE}"
|
||
echo "🌐 使用命名隧道运行(前台)"
|
||
exec cloudflared tunnel run --config "$CONFIG_FILE"
|
||
fi
|
||
|
||
echo "⚠️ 未检测到命名隧道配置,自动切换临时隧道。"
|
||
echo " 若需固定域名,请先执行: ${SETUP_SCRIPT}"
|
||
run_quick_tunnels
|