chore: remove confirmed stale workspace artifacts
This commit is contained in:
parent
1d34e32788
commit
d5e76d67d2
Binary file not shown.
|
Before Width: | Height: | Size: 254 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 227 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 85 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 221 KiB |
|
|
@ -1,105 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Cloudflare Tunnel Setup Script for PMFlow
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
echo "🚀 Starting Cloudflare Tunnel Setup..."
|
|
||||||
|
|
||||||
# Check if cloudflared is installed
|
|
||||||
if ! command -v cloudflared &> /dev/null; then
|
|
||||||
echo "❌ cloudflared is not installed. Please install it first:"
|
|
||||||
echo " brew install cloudflared"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Ask for configuration
|
|
||||||
read -p "Enter your Frontend domain (e.g., pmflow.com): " FRONTEND_DOMAIN
|
|
||||||
read -p "Enter your Backend domain (e.g., api.pmflow.com): " BACKEND_DOMAIN
|
|
||||||
read -p "Enter a name for your tunnel (e.g., pmflow-tunnel): " TUNNEL_NAME
|
|
||||||
|
|
||||||
if [ -z "$FRONTEND_DOMAIN" ] || [ -z "$BACKEND_DOMAIN" ] || [ -z "$TUNNEL_NAME" ]; then
|
|
||||||
echo "❌ Frontend domain, Backend domain, and Tunnel name are required."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Checking authentication..."
|
|
||||||
# Check if cert.pem exists in default location
|
|
||||||
if [ ! -f "$HOME/.cloudflared/cert.pem" ]; then
|
|
||||||
echo "⚠️ You need to login to Cloudflare first."
|
|
||||||
cloudflared tunnel login
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Creating tunnel '$TUNNEL_NAME'..."
|
|
||||||
# Check if tunnel exists, if not create it
|
|
||||||
if ! cloudflared tunnel list | grep -q "$TUNNEL_NAME"; then
|
|
||||||
cloudflared tunnel create "$TUNNEL_NAME"
|
|
||||||
else
|
|
||||||
echo "ℹ️ Tunnel '$TUNNEL_NAME' already exists."
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Routing DNS..."
|
|
||||||
# Route DNS for both domains
|
|
||||||
cloudflared tunnel route dns "$TUNNEL_NAME" "$FRONTEND_DOMAIN"
|
|
||||||
cloudflared tunnel route dns "$TUNNEL_NAME" "$BACKEND_DOMAIN"
|
|
||||||
|
|
||||||
# Get Tunnel ID
|
|
||||||
TUNNEL_ID=$(cloudflared tunnel list | grep "$TUNNEL_NAME" | awk '{print $1}')
|
|
||||||
|
|
||||||
if [ -z "$TUNNEL_ID" ]; then
|
|
||||||
echo "❌ Could not find Tunnel ID for '$TUNNEL_NAME'"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Generating config file..."
|
|
||||||
# Create config.yml
|
|
||||||
mkdir -p devops/tunnel
|
|
||||||
cat > devops/tunnel/config.yml <<EOF
|
|
||||||
tunnel: $TUNNEL_ID
|
|
||||||
credentials-file: $HOME/.cloudflared/$TUNNEL_ID.json
|
|
||||||
|
|
||||||
ingress:
|
|
||||||
- hostname: $FRONTEND_DOMAIN
|
|
||||||
service: http://localhost:5174
|
|
||||||
- hostname: $BACKEND_DOMAIN
|
|
||||||
service: http://localhost:8000
|
|
||||||
- service: http_status:404
|
|
||||||
EOF
|
|
||||||
|
|
||||||
echo "✅ Tunnel configuration created at devops/tunnel/config.yml"
|
|
||||||
|
|
||||||
# Update .env file in frontend
|
|
||||||
ENV_FILE="frontend/.env"
|
|
||||||
if [ ! -f "$ENV_FILE" ]; then
|
|
||||||
touch "$ENV_FILE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Update VITE_APP_DOMAIN and VITE_API_BASE_URL
|
|
||||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
||||||
sed -i '' "s|VITE_APP_DOMAIN=.*|VITE_APP_DOMAIN=$FRONTEND_DOMAIN|" "$ENV_FILE"
|
|
||||||
# Check if VITE_API_BASE_URL exists, if so replace it, else append
|
|
||||||
if grep -q "VITE_API_BASE_URL=" "$ENV_FILE"; then
|
|
||||||
sed -i '' "s|VITE_API_BASE_URL=.*|VITE_API_BASE_URL=https://$BACKEND_DOMAIN|" "$ENV_FILE"
|
|
||||||
else
|
|
||||||
echo "VITE_API_BASE_URL=https://$BACKEND_DOMAIN" >> "$ENV_FILE"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
sed -i "s|VITE_APP_DOMAIN=.*|VITE_APP_DOMAIN=$FRONTEND_DOMAIN|" "$ENV_FILE"
|
|
||||||
if grep -q "VITE_API_BASE_URL=" "$ENV_FILE"; then
|
|
||||||
sed -i "s|VITE_API_BASE_URL=.*|VITE_API_BASE_URL=https://$BACKEND_DOMAIN|" "$ENV_FILE"
|
|
||||||
else
|
|
||||||
echo "VITE_API_BASE_URL=https://$BACKEND_DOMAIN" >> "$ENV_FILE"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! grep -q "VITE_APP_DOMAIN=" "$ENV_FILE"; then
|
|
||||||
echo "VITE_APP_DOMAIN=$FRONTEND_DOMAIN" >> "$ENV_FILE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "✅ Updated $ENV_FILE with:"
|
|
||||||
echo " VITE_APP_DOMAIN=$FRONTEND_DOMAIN"
|
|
||||||
echo " VITE_API_BASE_URL=https://$BACKEND_DOMAIN"
|
|
||||||
|
|
||||||
echo "🎉 Setup complete! You can now run the tunnel with:"
|
|
||||||
echo " ./devops/tunnel/start.sh"
|
|
||||||
|
|
||||||
|
|
@ -1,135 +0,0 @@
|
||||||
#!/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
|
|
||||||
|
|
@ -1,340 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
set -uo pipefail
|
|
||||||
|
|
||||||
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
||||||
cd "$PROJECT_DIR"
|
|
||||||
|
|
||||||
mkdir -p logs
|
|
||||||
|
|
||||||
PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:${PATH:-}"
|
|
||||||
URL_PATTERN='https://[a-z0-9-]+\.trycloudflare\.com'
|
|
||||||
WATCH_LOG="logs/tunnel-frontend-watch.log"
|
|
||||||
WATCH_STDOUT_LOG="logs/tunnel-frontend-watch.stdout"
|
|
||||||
WATCH_PID_FILE="logs/tunnel-frontend-watch.pid"
|
|
||||||
RUN_LOG="logs/tunnel-frontend.log"
|
|
||||||
TUNNEL_PID_FILE="logs/tunnel-frontend.pid"
|
|
||||||
PUBLIC_URL_FILE="logs/public_url.txt"
|
|
||||||
ACTIVE_CHILD_PID=""
|
|
||||||
|
|
||||||
is_pid_running() {
|
|
||||||
local pid="${1:-}"
|
|
||||||
[[ -n "$pid" ]] || return 1
|
|
||||||
ps -p "$pid" >/dev/null 2>&1
|
|
||||||
}
|
|
||||||
|
|
||||||
log_watch() {
|
|
||||||
local message="$1"
|
|
||||||
local line="[$(date '+%Y-%m-%d %H:%M:%S')] [watch] ${message}"
|
|
||||||
printf '%s\n' "$line" | tee -a "$WATCH_LOG"
|
|
||||||
}
|
|
||||||
|
|
||||||
log_watch_err() {
|
|
||||||
local message="$1"
|
|
||||||
local line="[$(date '+%Y-%m-%d %H:%M:%S')] [watch] ${message}"
|
|
||||||
printf '%s\n' "$line" | tee -a "$WATCH_LOG" >&2
|
|
||||||
}
|
|
||||||
|
|
||||||
read_frontend_url() {
|
|
||||||
local line=""
|
|
||||||
line="$(rg '^frontend=' "$PUBLIC_URL_FILE" 2>/dev/null | tail -n 1 || true)"
|
|
||||||
if [[ -n "$line" ]]; then
|
|
||||||
echo "${line#frontend=}"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
sed -n '1p' "$PUBLIC_URL_FILE" 2>/dev/null | rg '^https?://' -N || true
|
|
||||||
}
|
|
||||||
|
|
||||||
read_backend_url() {
|
|
||||||
local line=""
|
|
||||||
line="$(rg '^backend=' "$PUBLIC_URL_FILE" 2>/dev/null | tail -n 1 || true)"
|
|
||||||
if [[ -n "$line" ]]; then
|
|
||||||
echo "${line#backend=}"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
sed -n '2p' "$PUBLIC_URL_FILE" 2>/dev/null | rg '^https?://' -N || true
|
|
||||||
}
|
|
||||||
|
|
||||||
write_frontend_url() {
|
|
||||||
local frontend_url="$1"
|
|
||||||
local backend_url=""
|
|
||||||
backend_url="$(read_backend_url)"
|
|
||||||
: > "$PUBLIC_URL_FILE"
|
|
||||||
echo "frontend=$frontend_url" >> "$PUBLIC_URL_FILE"
|
|
||||||
if [[ -n "$backend_url" ]]; then
|
|
||||||
echo "backend=$backend_url" >> "$PUBLIC_URL_FILE"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
find_cloudflared_bin() {
|
|
||||||
local bin
|
|
||||||
bin="$(command -v cloudflared || true)"
|
|
||||||
if [[ -n "$bin" ]]; then
|
|
||||||
echo "$bin"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
for candidate in /opt/homebrew/bin/cloudflared /usr/local/bin/cloudflared; do
|
|
||||||
if [[ -x "$candidate" ]]; then
|
|
||||||
echo "$candidate"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
echo ""
|
|
||||||
}
|
|
||||||
|
|
||||||
extract_tunnel_url() {
|
|
||||||
local logfile="$1"
|
|
||||||
rg -o "$URL_PATTERN" "$logfile" 2>/dev/null \
|
|
||||||
| rg -v "^https://api\\.trycloudflare\\.com$" \
|
|
||||||
| tail -n 1
|
|
||||||
}
|
|
||||||
|
|
||||||
probe_local_origin() {
|
|
||||||
local port="$1"
|
|
||||||
local code=""
|
|
||||||
code="$(curl --noproxy '*' -s -m 3 -o /dev/null -w "%{http_code}" "http://127.0.0.1:${port}/" || true)"
|
|
||||||
[[ "$code" =~ ^[0-9]{3}$ ]] || return 1
|
|
||||||
[[ "$code" -ge 200 && "$code" -lt 500 ]]
|
|
||||||
}
|
|
||||||
|
|
||||||
probe_tunnel_url() {
|
|
||||||
local url="$1"
|
|
||||||
local code=""
|
|
||||||
code="$(curl --noproxy '*' -s -m 8 -o /dev/null -w "%{http_code}" "${url}/" || true)"
|
|
||||||
[[ "$code" =~ ^[0-9]{3}$ ]] || return 1
|
|
||||||
[[ "$code" -ge 200 && "$code" -lt 500 ]]
|
|
||||||
}
|
|
||||||
|
|
||||||
probe_tunnel_url_stable() {
|
|
||||||
local url="$1"
|
|
||||||
local checks="${2:-2}"
|
|
||||||
local current=1
|
|
||||||
while [[ "$current" -le "$checks" ]]; do
|
|
||||||
probe_tunnel_url "$url" || return 1
|
|
||||||
if [[ "$current" -lt "$checks" ]]; then
|
|
||||||
sleep 1
|
|
||||||
fi
|
|
||||||
current=$((current + 1))
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve_frontend_port() {
|
|
||||||
local preferred="${PMFLOW_FRONTEND_TUNNEL_PORT:-${FRONTEND_PORT:-5174}}"
|
|
||||||
local candidates=("$preferred" 5174 5175 5176 5177 5178)
|
|
||||||
local seen=" "
|
|
||||||
local port=""
|
|
||||||
for port in "${candidates[@]}"; do
|
|
||||||
[[ "$seen" == *" ${port} "* ]] && continue
|
|
||||||
seen="${seen}${port} "
|
|
||||||
if probe_local_origin "$port"; then
|
|
||||||
echo "$port"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
echo "$preferred"
|
|
||||||
}
|
|
||||||
|
|
||||||
is_watch_running() {
|
|
||||||
if [[ ! -f "$WATCH_PID_FILE" ]]; then
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
local pid
|
|
||||||
pid="$(cat "$WATCH_PID_FILE" 2>/dev/null || true)"
|
|
||||||
if [[ -z "$pid" ]]; then
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
if ps -p "$pid" >/dev/null 2>&1; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup_children() {
|
|
||||||
if [[ -n "${ACTIVE_CHILD_PID:-}" ]] && is_pid_running "$ACTIVE_CHILD_PID"; then
|
|
||||||
kill "$ACTIVE_CHILD_PID" >/dev/null 2>&1 || true
|
|
||||||
fi
|
|
||||||
if [[ -f "$TUNNEL_PID_FILE" ]]; then
|
|
||||||
local pid
|
|
||||||
pid="$(cat "$TUNNEL_PID_FILE" 2>/dev/null || true)"
|
|
||||||
if [[ -n "$pid" ]] && is_pid_running "$pid"; then
|
|
||||||
kill "$pid" >/dev/null 2>&1 || true
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
stop_watch() {
|
|
||||||
local stopped=0
|
|
||||||
if [[ -f "$WATCH_PID_FILE" ]]; then
|
|
||||||
local wpid
|
|
||||||
wpid="$(cat "$WATCH_PID_FILE" 2>/dev/null || true)"
|
|
||||||
if [[ -n "$wpid" ]] && is_pid_running "$wpid"; then
|
|
||||||
kill "$wpid" >/dev/null 2>&1 || true
|
|
||||||
stopped=1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
cleanup_children
|
|
||||||
rm -f "$WATCH_PID_FILE" "$TUNNEL_PID_FILE"
|
|
||||||
if [[ "$stopped" -eq 1 ]]; then
|
|
||||||
echo "[前端隧道守护] 已停止"
|
|
||||||
else
|
|
||||||
echo "[前端隧道守护] 未运行"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
print_status() {
|
|
||||||
local tunnel_pid=""
|
|
||||||
if [[ -f "$TUNNEL_PID_FILE" ]]; then
|
|
||||||
tunnel_pid="$(cat "$TUNNEL_PID_FILE" 2>/dev/null || true)"
|
|
||||||
fi
|
|
||||||
if is_watch_running; then
|
|
||||||
local wpid cpid
|
|
||||||
wpid="$(cat "$WATCH_PID_FILE" 2>/dev/null || true)"
|
|
||||||
cpid="${tunnel_pid:-$(cat "$TUNNEL_PID_FILE" 2>/dev/null || true)}"
|
|
||||||
echo "[前端隧道守护] 运行中 watch_pid=${wpid:-unknown} tunnel_pid=${cpid:-unknown}"
|
|
||||||
else
|
|
||||||
echo "[前端隧道守护] 未运行"
|
|
||||||
fi
|
|
||||||
local frontend_url backend_url
|
|
||||||
frontend_url="$(read_frontend_url)"
|
|
||||||
backend_url="$(read_backend_url)"
|
|
||||||
if [[ -n "$frontend_url" ]]; then
|
|
||||||
echo "前端地址: $frontend_url"
|
|
||||||
if is_pid_running "$tunnel_pid"; then
|
|
||||||
echo "前端健康: tunnel进程运行中"
|
|
||||||
else
|
|
||||||
echo "前端健康: tunnel进程未运行"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "前端地址: (空)"
|
|
||||||
fi
|
|
||||||
if [[ -n "$backend_url" ]]; then
|
|
||||||
echo "后端地址: $backend_url"
|
|
||||||
else
|
|
||||||
echo "后端地址: (未配置/未暴露)"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
start_watch_background() {
|
|
||||||
if is_watch_running; then
|
|
||||||
print_status
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
nohup bash "$0" run >"$WATCH_STDOUT_LOG" 2>&1 &
|
|
||||||
local pid="$!"
|
|
||||||
echo "$pid" >"$WATCH_PID_FILE"
|
|
||||||
echo "[前端隧道守护] 已启动 pid=$pid"
|
|
||||||
sleep 1
|
|
||||||
tail -n 5 "$WATCH_STDOUT_LOG" 2>/dev/null || true
|
|
||||||
}
|
|
||||||
|
|
||||||
run_watch_loop() {
|
|
||||||
local cf_bin
|
|
||||||
cf_bin="$(find_cloudflared_bin)"
|
|
||||||
if [[ -z "$cf_bin" ]]; then
|
|
||||||
log_watch_err "cloudflared_not_found"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "$$" >"$WATCH_PID_FILE"
|
|
||||||
log_watch "start bin=$cf_bin"
|
|
||||||
trap 'cleanup_children; rm -f "$WATCH_PID_FILE"; log_watch "exit code=$?"' EXIT INT TERM
|
|
||||||
|
|
||||||
while true; do
|
|
||||||
local frontend_port tunnel_protocol child_pid published current_url url
|
|
||||||
local strict_public_health public_health_interval public_health_failure_threshold
|
|
||||||
local unhealthy_count last_health_check_at
|
|
||||||
frontend_port="$(resolve_frontend_port)"
|
|
||||||
tunnel_protocol="${PMFLOW_TUNNEL_PROTOCOL_FRONTEND:-${PMFLOW_TUNNEL_PROTOCOL:-http2}}"
|
|
||||||
strict_public_health="${PMFLOW_TUNNEL_STRICT_PUBLIC_HEALTH:-0}"
|
|
||||||
public_health_interval="${PMFLOW_TUNNEL_PUBLIC_HEALTH_INTERVAL_SECONDS:-30}"
|
|
||||||
public_health_failure_threshold="${PMFLOW_TUNNEL_PUBLIC_HEALTH_FAILURE_THRESHOLD:-5}"
|
|
||||||
: > "$RUN_LOG"
|
|
||||||
log_watch "origin=http://127.0.0.1:${frontend_port} protocol=${tunnel_protocol}"
|
|
||||||
|
|
||||||
env -u HTTPS_PROXY -u HTTP_PROXY -u ALL_PROXY -u https_proxy -u http_proxy -u all_proxy \
|
|
||||||
NO_PROXY="*" \
|
|
||||||
"$cf_bin" tunnel --protocol "$tunnel_protocol" --url "http://127.0.0.1:${frontend_port}" >"$RUN_LOG" 2>&1 &
|
|
||||||
child_pid="$!"
|
|
||||||
ACTIVE_CHILD_PID="$child_pid"
|
|
||||||
echo "$child_pid" > "$TUNNEL_PID_FILE"
|
|
||||||
|
|
||||||
published="0"
|
|
||||||
current_url=""
|
|
||||||
for _ in {1..90}; do
|
|
||||||
url="$(extract_tunnel_url "$RUN_LOG" || true)"
|
|
||||||
if [[ -n "$url" ]]; then
|
|
||||||
if [[ "$strict_public_health" == "1" ]] && ! probe_tunnel_url_stable "$url"; then
|
|
||||||
:
|
|
||||||
else
|
|
||||||
if [[ "$url" != "$current_url" ]]; then
|
|
||||||
write_frontend_url "$url"
|
|
||||||
log_watch "url=$url"
|
|
||||||
fi
|
|
||||||
current_url="$url"
|
|
||||||
published="1"
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
if ! is_pid_running "$child_pid"; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
|
|
||||||
unhealthy_count=0
|
|
||||||
last_health_check_at=0
|
|
||||||
while is_pid_running "$child_pid"; do
|
|
||||||
if [[ "$strict_public_health" == "1" && "$published" == "1" && -n "$current_url" ]]; then
|
|
||||||
if (( $(date +%s) - last_health_check_at >= public_health_interval )); then
|
|
||||||
last_health_check_at="$(date +%s)"
|
|
||||||
if probe_tunnel_url "$current_url"; then
|
|
||||||
unhealthy_count=0
|
|
||||||
else
|
|
||||||
unhealthy_count=$((unhealthy_count + 1))
|
|
||||||
log_watch_err "health_check_failed url=${current_url} count=${unhealthy_count}"
|
|
||||||
fi
|
|
||||||
if [[ "$unhealthy_count" -ge "$public_health_failure_threshold" ]]; then
|
|
||||||
log_watch_err "url_unhealthy_restart url=${current_url}"
|
|
||||||
kill "$child_pid" >/dev/null 2>&1 || true
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
sleep 5
|
|
||||||
done
|
|
||||||
|
|
||||||
wait "$child_pid" || true
|
|
||||||
ACTIVE_CHILD_PID=""
|
|
||||||
if [[ "$published" != "1" ]]; then
|
|
||||||
log_watch_err "exited_before_url"
|
|
||||||
else
|
|
||||||
log_watch_err "exited_restart"
|
|
||||||
fi
|
|
||||||
sleep 2
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd="${1:-run}"
|
|
||||||
case "$cmd" in
|
|
||||||
run)
|
|
||||||
run_watch_loop
|
|
||||||
;;
|
|
||||||
start)
|
|
||||||
start_watch_background
|
|
||||||
;;
|
|
||||||
stop)
|
|
||||||
stop_watch
|
|
||||||
;;
|
|
||||||
status)
|
|
||||||
print_status
|
|
||||||
;;
|
|
||||||
url)
|
|
||||||
front="$(read_frontend_url)"
|
|
||||||
back="$(read_backend_url)"
|
|
||||||
echo "前端地址: ${front:-未就绪}"
|
|
||||||
echo "后端地址: ${back:-未配置/未暴露}"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Usage: $0 {run|start|stop|status|url}"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -1,36 +0,0 @@
|
||||||
<!doctype html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<title>短确认验收结果</title>
|
|
||||||
<style>
|
|
||||||
body { font-family: Menlo, Monaco, 'SF Mono', monospace; background:#f6f7f9; margin:24px; }
|
|
||||||
.card { background:#fff; border:1px solid #d9dde3; border-radius:10px; padding:16px; }
|
|
||||||
h1 { margin:0 0 10px 0; font-size:20px; }
|
|
||||||
p { margin:6px 0; font-size:13px; }
|
|
||||||
.bad { color:#b42318; font-weight:700; }
|
|
||||||
.ok { color:#027a48; font-weight:700; }
|
|
||||||
pre { background:#f8fafc; border:1px solid #e4e7ec; border-radius:8px; padding:10px; white-space:pre-wrap; word-break:break-word; font-size:12px; }
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="card">
|
|
||||||
<h1>短确认重设计验收(消息1写操作场景)</h1>
|
|
||||||
<p>消息1 ID: accept-shortconfirm-redesign-msg1-1773935717</p>
|
|
||||||
<p>消息2 ID: accept-shortconfirm-redesign-msg2-1773935717</p>
|
|
||||||
<p>消息1 intent: <span class="bad">query.answer</span>(预期 signal.create)</p>
|
|
||||||
<p>消息2 context_source: <span class="ok">session_inherited</span></p>
|
|
||||||
<p>消息2 intent: <span class="bad">query.answer</span>(继承了消息1的查询意图)</p>
|
|
||||||
<p>消息2 classify_intent_ai_pmo_kernel 调用: <span class="ok">无</span></p>
|
|
||||||
<p>消息2 LLM 调用: <span class="bad">有</span>(adaptive_rag_answer_normal)</p>
|
|
||||||
<pre>ai_call_logs:
|
|
||||||
1932 classify_intent_ai_pmo_kernel hit_msg1=1 hit_msg2=0
|
|
||||||
1933 adaptive_rag_answer_normal hit_msg1=1 hit_msg2=0
|
|
||||||
1934 adaptive_rag_answer_normal hit_msg1=0 hit_msg2=1
|
|
||||||
|
|
||||||
work_items:
|
|
||||||
397 source=msg1 state=failed intent=query.answer context_source=llm_only
|
|
||||||
398 source=msg2 state=succeeded intent=query.answer context_source=session_inherited</pre>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue