包含前端(Vue3 + VueFlow 画布)、后端(Go)、文档体系。 - 工作台画布:节点拖放、连线模式、右键菜单、AI 助手 - 后端:连接器 API、专员种子数据 - 导航:左侧导航、工坊、市场、控制台
286 lines
8.1 KiB
Bash
286 lines
8.1 KiB
Bash
#!/usr/bin/env bash
|
|
if [ -z "${BASH_VERSION:-}" ]; then
|
|
if command -v bash >/dev/null 2>&1; then
|
|
echo "[INFO] start_dev_10231_10232.sh requires bash. Re-running with bash ..."
|
|
exec bash "$0" "$@"
|
|
fi
|
|
echo "[FATAL] bash is required but was not found on PATH." >&2
|
|
echo " Please run: bash ./start_dev_10231_10232.sh" >&2
|
|
exit 1
|
|
fi
|
|
|
|
set -euo pipefail
|
|
|
|
FORCE=0
|
|
SKIP_PREFLIGHT=0
|
|
SKIP_SMOKE=0
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--force|-f)
|
|
FORCE=1
|
|
;;
|
|
--skip-preflight)
|
|
SKIP_PREFLIGHT=1
|
|
;;
|
|
--skip-smoke)
|
|
SKIP_SMOKE=1
|
|
;;
|
|
--help|-h)
|
|
cat <<'EOF'
|
|
Usage: ./start_dev_10231_10232.sh [options]
|
|
|
|
Options:
|
|
--force Kill processes occupying the frontend/backend ports
|
|
--skip-preflight Skip preflight checks
|
|
--skip-smoke Skip admin account smoke login
|
|
--help Show this help
|
|
EOF
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "[FATAL] Unknown option: $1" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
OURS=(eaisalestrain-server node npm vite)
|
|
BACKEND_PORT=10232
|
|
FRONTEND_PORT=10231
|
|
|
|
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
APP_DIR="$REPO_DIR/eai_ap_app"
|
|
BACKEND_DIR="$APP_DIR/backend-go"
|
|
BACKEND_BIN="$BACKEND_DIR/bin/eaisalestrain-server"
|
|
FRONTEND_DIR="$APP_DIR/frontend"
|
|
DEV_BIND_HOST="${EAI_DEV_BIND_HOST:-127.0.0.1}"
|
|
DEBUG_LOG_DIR="$REPO_DIR/debuglog"
|
|
mkdir -p "$DEBUG_LOG_DIR"
|
|
|
|
RUN_ID="$(date +%Y%m%d_%H%M%S)"
|
|
BACKEND_LOG="$DEBUG_LOG_DIR/backend_${RUN_ID}.log"
|
|
FRONTEND_LOG="$DEBUG_LOG_DIR/frontend_${RUN_ID}.log"
|
|
BACKEND_PID_FILE="$DEBUG_LOG_DIR/backend.pid"
|
|
FRONTEND_PID_FILE="$DEBUG_LOG_DIR/frontend.pid"
|
|
|
|
check() {
|
|
local label="$1"
|
|
local fix_hint="$2"
|
|
shift 2
|
|
printf ' [.] %s ...' "$label"
|
|
if "$@" >/dev/null 2>&1; then
|
|
printf ' OK\n'
|
|
return 0
|
|
fi
|
|
printf ' FAIL\n'
|
|
if [[ -n "$fix_hint" ]]; then
|
|
printf ' fix: %s\n' "$fix_hint"
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
wait_health() {
|
|
local url="$1"
|
|
local label="$2"
|
|
local timeout_sec="${3:-60}"
|
|
local elapsed=0
|
|
printf ' [.] waiting on %s (%s) ...' "$label" "$url"
|
|
while (( elapsed < timeout_sec )); do
|
|
if curl -fsS --max-time 2 "$url" >/dev/null 2>&1; then
|
|
printf ' READY\n'
|
|
return 0
|
|
fi
|
|
sleep 1
|
|
elapsed=$((elapsed + 1))
|
|
printf '.'
|
|
done
|
|
printf ' TIMEOUT\n'
|
|
return 1
|
|
}
|
|
|
|
detect_public_host() {
|
|
local candidate
|
|
for candidate in $(hostname -I 2>/dev/null || true); do
|
|
case "$candidate" in
|
|
127.*|172.17.*)
|
|
continue
|
|
;;
|
|
*)
|
|
echo "$candidate"
|
|
return 0
|
|
;;
|
|
esac
|
|
done
|
|
echo "127.0.0.1"
|
|
}
|
|
|
|
port_pids() {
|
|
local port="$1"
|
|
if command -v lsof >/dev/null 2>&1; then
|
|
lsof -tiTCP:"$port" -sTCP:LISTEN 2>/dev/null | sort -u
|
|
return 0
|
|
fi
|
|
if command -v ss >/dev/null 2>&1; then
|
|
ss -ltnp "( sport = :$port )" 2>/dev/null | awk -F'pid=' 'NR>1 && NF>1 {split($2,a,","); print a[1]}' | sort -u
|
|
return 0
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
resolve_port() {
|
|
local port="$1"
|
|
local label="$2"
|
|
local pids raw_comm
|
|
mapfile -t pids < <(port_pids "$port" || true)
|
|
if [[ ${#pids[@]} -eq 0 ]]; then
|
|
printf ' [.] %s :%s free\n' "$label" "$port"
|
|
return 0
|
|
fi
|
|
|
|
printf ' [!] %s :%s in use by ' "$label" "$port"
|
|
for pid in "${pids[@]}"; do
|
|
raw_comm="$(ps -p "$pid" -o comm= 2>/dev/null | xargs || echo unknown)"
|
|
printf '%s(PID %s) ' "$raw_comm" "$pid"
|
|
done
|
|
printf '\n'
|
|
|
|
for pid in "${pids[@]}"; do
|
|
raw_comm="$(ps -p "$pid" -o comm= 2>/dev/null | xargs || echo unknown)"
|
|
if [[ "$FORCE" -eq 1 || " ${OURS[*]} " == *" $raw_comm "* ]]; then
|
|
printf ' killing %s(PID %s)\n' "$raw_comm" "$pid"
|
|
kill "$pid" 2>/dev/null || true
|
|
sleep 1
|
|
kill -9 "$pid" 2>/dev/null || true
|
|
else
|
|
printf ' keeping non-project process: %s(PID %s)\n' "$raw_comm" "$pid"
|
|
printf ' fix: stop that process manually, or rerun with --force\n'
|
|
return 1
|
|
fi
|
|
done
|
|
|
|
mapfile -t pids < <(port_pids "$port" || true)
|
|
if [[ ${#pids[@]} -gt 0 ]]; then
|
|
printf ' [FAIL] %s :%s still in use\n' "$label" "$port"
|
|
return 1
|
|
fi
|
|
|
|
printf ' [OK] %s :%s released\n' "$label" "$port"
|
|
return 0
|
|
}
|
|
|
|
cleanup_started() {
|
|
if [[ -f "$BACKEND_PID_FILE" ]]; then
|
|
kill "$(cat "$BACKEND_PID_FILE")" 2>/dev/null || true
|
|
fi
|
|
if [[ -f "$FRONTEND_PID_FILE" ]]; then
|
|
kill "$(cat "$FRONTEND_PID_FILE")" 2>/dev/null || true
|
|
fi
|
|
}
|
|
|
|
echo "==> eaisalestrain dev launcher"
|
|
echo " repo : $REPO_DIR"
|
|
echo " backend : $BACKEND_DIR (port $BACKEND_PORT)"
|
|
echo " frontend : $FRONTEND_DIR (port $FRONTEND_PORT)"
|
|
echo " bind host: $DEV_BIND_HOST"
|
|
echo
|
|
|
|
if [[ "${EAI_DEV_PUBLIC_HOST:-}" != "" ]]; then
|
|
DEV_PUBLIC_HOST="$EAI_DEV_PUBLIC_HOST"
|
|
elif [[ "$DEV_BIND_HOST" == "0.0.0.0" ]]; then
|
|
DEV_PUBLIC_HOST="$(detect_public_host)"
|
|
else
|
|
DEV_PUBLIC_HOST="$DEV_BIND_HOST"
|
|
fi
|
|
|
|
if [[ "$SKIP_PREFLIGHT" -eq 0 ]]; then
|
|
echo "[1/4] preflight checks"
|
|
all_ok=1
|
|
check "backend dir exists" "run from repo root" test -d "$BACKEND_DIR" || all_ok=0
|
|
check "backend binary built" "cd backend-go && go build ./cmd/server" test -f "$BACKEND_BIN" || all_ok=0
|
|
check "frontend dir exists" "run from repo root" test -d "$FRONTEND_DIR" || all_ok=0
|
|
check "frontend node_modules" "run npm install in frontend/" test -e "$FRONTEND_DIR/node_modules" || all_ok=0
|
|
check "node on PATH" "install nodejs" command -v node || all_ok=0
|
|
check "npm on PATH" "install npm" command -v npm || all_ok=0
|
|
check "curl on PATH" "install curl" command -v curl || all_ok=0
|
|
if [[ "$all_ok" -eq 0 ]]; then
|
|
echo
|
|
echo "[ABORT] preflight failed."
|
|
exit 1
|
|
fi
|
|
echo
|
|
else
|
|
echo "[1/4] preflight skipped (--skip-preflight)"
|
|
echo
|
|
fi
|
|
|
|
echo "[2/4] port conflict check"
|
|
resolve_port "$BACKEND_PORT" "backend" || exit 1
|
|
resolve_port "$FRONTEND_PORT" "frontend" || exit 1
|
|
echo
|
|
|
|
trap cleanup_started EXIT
|
|
|
|
echo "[3/4] launch services"
|
|
echo " [.] starting backend (eaisalestrain-server :$BACKEND_PORT)"
|
|
echo " [.] log : $BACKEND_LOG"
|
|
nohup env PORT="$BACKEND_PORT" "$BACKEND_BIN" >>"$BACKEND_LOG" 2>&1 </dev/null &
|
|
BACKEND_PID=$!
|
|
echo "$BACKEND_PID" > "$BACKEND_PID_FILE"
|
|
|
|
if ! wait_health "http://127.0.0.1:$BACKEND_PORT/api/health" "backend"; then
|
|
echo
|
|
echo "[ABORT] backend did not become healthy, frontend not started."
|
|
echo " check: $BACKEND_LOG"
|
|
exit 1
|
|
fi
|
|
|
|
echo " [.] starting frontend (vite :$FRONTEND_PORT)"
|
|
echo " [.] log : $FRONTEND_LOG"
|
|
nohup bash -lc "cd \"$FRONTEND_DIR\" && exec node ./node_modules/vite/bin/vite.js --host \"$DEV_BIND_HOST\" --port \"$FRONTEND_PORT\"" >>"$FRONTEND_LOG" 2>&1 </dev/null &
|
|
FRONTEND_PID=$!
|
|
echo "$FRONTEND_PID" > "$FRONTEND_PID_FILE"
|
|
echo
|
|
|
|
echo "[4/4] health check + smoke login"
|
|
f_ok=1
|
|
if ! wait_health "http://127.0.0.1:$FRONTEND_PORT/" "frontend"; then
|
|
f_ok=0
|
|
fi
|
|
|
|
if [[ "$SKIP_SMOKE" -eq 0 && "$f_ok" -eq 1 ]]; then
|
|
echo
|
|
echo " [.] smoke login admin account ..."
|
|
payload='{"username":"admin","password":"admin123"}'
|
|
status_code="$(curl -sS -o /dev/null -w '%{http_code}' \
|
|
-H 'Content-Type: application/json' \
|
|
-d "$payload" \
|
|
"http://127.0.0.1:$BACKEND_PORT/api/auth/login" || true)"
|
|
if [[ "$status_code" == "200" ]]; then
|
|
printf ' [OK] admin login success\n'
|
|
else
|
|
printf ' [FAIL] admin login (HTTP %s)\n' "$status_code"
|
|
fi
|
|
else
|
|
echo " [.] smoke login skipped"
|
|
fi
|
|
|
|
echo
|
|
echo "================================================================="
|
|
echo " Service status"
|
|
echo "================================================================="
|
|
echo " backend : http://$DEV_PUBLIC_HOST:$BACKEND_PORT"
|
|
echo " frontend : http://$DEV_PUBLIC_HOST:$FRONTEND_PORT"
|
|
echo " backend log : $BACKEND_LOG"
|
|
echo " frontend log: $FRONTEND_LOG"
|
|
echo " PIDs: backend=$BACKEND_PID frontend=$FRONTEND_PID"
|
|
echo "================================================================="
|
|
echo
|
|
|
|
trap - EXIT
|
|
echo "Usage: ./start_dev_10231_10232.sh [--force] [--skip-preflight]"
|
|
echo " env: EAI_DEV_BIND_HOST=0.0.0.0 (listen all)"
|
|
echo " env: EAI_DEV_PUBLIC_HOST=x.x.x.x (public url)"
|
|
echo
|