CLAUDE: Improve service scripts and fix WebSocket plugin conflict
Service Scripts: - start-services.sh: Add pre-flight checks, health monitoring, --dev/--prod modes, port options, dependency checks, and version logging - stop-services.sh: Add port 3000 cleanup, verification, --quiet/--force flags - status-services.sh: New script for monitoring service status with --watch mode WebSocket: - Remove conflicting socket.client.ts plugin that was interfering with useWebSocket.ts composable (used JWT auth vs cookie auth) - Add debugging logs to useWebSocket.ts to diagnose intermittent connection issues 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
46cf1cc02b
commit
b68e3ceacf
@ -125,6 +125,15 @@ export function useWebSocket() {
|
||||
try {
|
||||
// Create or reuse socket instance
|
||||
if (!socketInstance) {
|
||||
console.log('[WebSocket] Creating socket instance with URL:', wsUrl)
|
||||
|
||||
if (!io) {
|
||||
console.error('[WebSocket] ERROR: io function is undefined!')
|
||||
connectionError.value = 'Socket.io library not loaded'
|
||||
isConnecting.value = false
|
||||
return
|
||||
}
|
||||
|
||||
socketInstance = io(wsUrl, {
|
||||
withCredentials: true, // Send cookies automatically
|
||||
autoConnect: false,
|
||||
@ -132,14 +141,17 @@ export function useWebSocket() {
|
||||
transports: ['websocket', 'polling'],
|
||||
})
|
||||
|
||||
console.log('[WebSocket] Socket instance created:', !!socketInstance)
|
||||
|
||||
setupEventListeners()
|
||||
}
|
||||
|
||||
console.log('[WebSocket] Calling socketInstance.connect()')
|
||||
socketInstance.connect()
|
||||
} catch (err) {
|
||||
console.error('[WebSocket] Connection error:', err)
|
||||
isConnecting.value = false
|
||||
connectionError.value = err instanceof Error ? err.message : 'Connection failed'
|
||||
connectionError.value = err instanceof Error ? err.message : String(err)
|
||||
if (connectionTimeoutId) {
|
||||
clearTimeout(connectionTimeoutId)
|
||||
connectionTimeoutId = null
|
||||
|
||||
@ -1,49 +0,0 @@
|
||||
import type { Socket } from 'socket.io-client';
|
||||
import { io } from 'socket.io-client'
|
||||
|
||||
export default defineNuxtPlugin((nuxtApp) => {
|
||||
const config = useRuntimeConfig()
|
||||
let socket: Socket | null = null
|
||||
|
||||
const connect = (token: string) => {
|
||||
if (socket?.connected) return socket
|
||||
|
||||
socket = io(config.public.wsUrl, {
|
||||
auth: { token },
|
||||
reconnection: true,
|
||||
reconnectionDelay: 1000,
|
||||
reconnectionAttempts: 5
|
||||
})
|
||||
|
||||
socket.on('connect', () => {
|
||||
console.log('WebSocket connected')
|
||||
})
|
||||
|
||||
socket.on('disconnect', () => {
|
||||
console.log('WebSocket disconnected')
|
||||
})
|
||||
|
||||
socket.on('connect_error', (error) => {
|
||||
console.error('WebSocket connection error:', error)
|
||||
})
|
||||
|
||||
return socket
|
||||
}
|
||||
|
||||
const disconnect = () => {
|
||||
socket?.disconnect()
|
||||
socket = null
|
||||
}
|
||||
|
||||
return {
|
||||
provide: {
|
||||
socket: {
|
||||
connect,
|
||||
disconnect,
|
||||
get instance() {
|
||||
return socket
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -1,48 +1,368 @@
|
||||
#!/bin/bash
|
||||
# Start both backend and frontend services for SBA gameplay testing
|
||||
# Enhanced with pre-flight checks, health monitoring, and version logging
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
LOG_DIR="$SCRIPT_DIR/logs"
|
||||
|
||||
# Default configuration
|
||||
BACKEND_PORT=8000
|
||||
FRONTEND_PORT=3000
|
||||
BACKEND_HOST="0.0.0.0"
|
||||
FRONTEND_HOST="0.0.0.0"
|
||||
HEALTH_CHECK_HOST="localhost" # For curl health checks
|
||||
|
||||
# Environment mode (affects .env file used)
|
||||
ENV_MODE="dev" # dev, prod, or custom
|
||||
|
||||
# Parse arguments
|
||||
FORCE_START=false
|
||||
FRONTEND_TYPE="sba" # Default to SBA frontend
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--force|-f)
|
||||
FORCE_START=true
|
||||
shift
|
||||
;;
|
||||
--frontend)
|
||||
FRONTEND_TYPE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--pd)
|
||||
FRONTEND_TYPE="pd"
|
||||
shift
|
||||
;;
|
||||
--dev)
|
||||
ENV_MODE="dev"
|
||||
shift
|
||||
;;
|
||||
--prod)
|
||||
ENV_MODE="prod"
|
||||
shift
|
||||
;;
|
||||
--backend-port)
|
||||
BACKEND_PORT="$2"
|
||||
shift 2
|
||||
;;
|
||||
--frontend-port)
|
||||
FRONTEND_PORT="$2"
|
||||
shift 2
|
||||
;;
|
||||
--help|-h)
|
||||
echo "Usage: $0 [OPTIONS]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --force, -f Force start (stop existing services first)"
|
||||
echo " --frontend TYPE Start specific frontend (sba or pd)"
|
||||
echo " --pd Shortcut for --frontend pd"
|
||||
echo " --dev Development mode - use localhost URLs (default)"
|
||||
echo " --prod Production mode - use .env production URLs"
|
||||
echo " --backend-port N Override backend port (default: 8000)"
|
||||
echo " --frontend-port N Override frontend port (default: 3000)"
|
||||
echo " --help, -h Show this help message"
|
||||
echo ""
|
||||
echo "Environment Modes:"
|
||||
echo " --dev Sets NUXT_PUBLIC_API_URL=http://localhost:8000"
|
||||
echo " Sets NUXT_PUBLIC_WS_URL=http://localhost:8000"
|
||||
echo ""
|
||||
echo " --prod Uses URLs from frontend-{sba,pd}/.env file"
|
||||
echo " (e.g., https://gameplay-demo.manticorum.com)"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Validate frontend type
|
||||
if [[ "$FRONTEND_TYPE" != "sba" && "$FRONTEND_TYPE" != "pd" ]]; then
|
||||
echo "❌ Invalid frontend type: $FRONTEND_TYPE (must be 'sba' or 'pd')"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
FRONTEND_DIR="$SCRIPT_DIR/frontend-$FRONTEND_TYPE"
|
||||
|
||||
# Create logs directory if it doesn't exist
|
||||
mkdir -p "$LOG_DIR"
|
||||
|
||||
echo "🚀 Starting SBA Gameplay Services..."
|
||||
echo "========================================"
|
||||
echo "🚀 Starting SBA Gameplay Services"
|
||||
echo "========================================"
|
||||
echo ""
|
||||
|
||||
# Start Backend
|
||||
# ============================================
|
||||
# PRE-FLIGHT CHECKS
|
||||
# ============================================
|
||||
echo "🔍 Pre-flight checks..."
|
||||
|
||||
# Check dependencies
|
||||
check_dependency() {
|
||||
if ! command -v "$1" &> /dev/null; then
|
||||
echo "❌ Required tool not found: $1"
|
||||
echo " Please install $1 before running this script."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_dependency "uv"
|
||||
check_dependency "npm"
|
||||
check_dependency "curl"
|
||||
echo " ✓ Dependencies available (uv, npm, curl)"
|
||||
|
||||
# Check if frontend directory exists
|
||||
if [ ! -d "$FRONTEND_DIR" ]; then
|
||||
echo "❌ Frontend directory not found: $FRONTEND_DIR"
|
||||
exit 1
|
||||
fi
|
||||
echo " ✓ Frontend directory exists: frontend-$FRONTEND_TYPE"
|
||||
|
||||
# Check if already running
|
||||
ALREADY_RUNNING=false
|
||||
|
||||
if [ -f "$LOG_DIR/backend.pid" ]; then
|
||||
EXISTING_PID=$(cat "$LOG_DIR/backend.pid")
|
||||
if ps -p "$EXISTING_PID" > /dev/null 2>&1; then
|
||||
ALREADY_RUNNING=true
|
||||
echo " ⚠️ Backend already running (PID: $EXISTING_PID)"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -f "$LOG_DIR/frontend.pid" ]; then
|
||||
EXISTING_PID=$(cat "$LOG_DIR/frontend.pid")
|
||||
if ps -p "$EXISTING_PID" > /dev/null 2>&1; then
|
||||
ALREADY_RUNNING=true
|
||||
echo " ⚠️ Frontend already running (PID: $EXISTING_PID)"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$ALREADY_RUNNING" = true ]; then
|
||||
if [ "$FORCE_START" = true ]; then
|
||||
echo " → Force flag set, stopping existing services..."
|
||||
"$SCRIPT_DIR/stop-services.sh"
|
||||
echo ""
|
||||
else
|
||||
echo ""
|
||||
echo "❌ Services already running. Use --force to restart or run ./stop-services.sh first."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check port availability
|
||||
check_port() {
|
||||
local port=$1
|
||||
local name=$2
|
||||
if lsof -ti :"$port" > /dev/null 2>&1; then
|
||||
echo " ⚠️ Port $port is in use ($name)"
|
||||
if [ "$FORCE_START" = true ]; then
|
||||
echo " → Force flag set, killing processes on port $port..."
|
||||
lsof -ti :"$port" | xargs kill -9 2>/dev/null || true
|
||||
sleep 1
|
||||
else
|
||||
echo ""
|
||||
echo "❌ Port $port is in use. Use --force to kill existing processes."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
check_port $BACKEND_PORT "backend"
|
||||
check_port $FRONTEND_PORT "frontend"
|
||||
echo " ✓ Ports $BACKEND_PORT and $FRONTEND_PORT available"
|
||||
|
||||
echo ""
|
||||
|
||||
# ============================================
|
||||
# VERSION LOGGING (helps debug deployment issues)
|
||||
# ============================================
|
||||
echo "📌 Version Info:"
|
||||
GIT_COMMIT=$(git -C "$SCRIPT_DIR" rev-parse --short HEAD 2>/dev/null || echo "unknown")
|
||||
GIT_BRANCH=$(git -C "$SCRIPT_DIR" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
|
||||
GIT_DIRTY=$(git -C "$SCRIPT_DIR" diff --quiet 2>/dev/null && echo "" || echo " (dirty)")
|
||||
TIMESTAMP=$(date -Iseconds)
|
||||
|
||||
echo " Branch: $GIT_BRANCH"
|
||||
echo " Commit: $GIT_COMMIT$GIT_DIRTY"
|
||||
echo " Started: $TIMESTAMP"
|
||||
|
||||
# Log to file for debugging
|
||||
cat > "$LOG_DIR/startup.log" << EOF
|
||||
========================================
|
||||
Service Startup Log
|
||||
========================================
|
||||
Timestamp: $TIMESTAMP
|
||||
Git Branch: $GIT_BRANCH
|
||||
Git Commit: $GIT_COMMIT$GIT_DIRTY
|
||||
Environment: $ENV_MODE
|
||||
Frontend: $FRONTEND_TYPE
|
||||
Backend Port: $BACKEND_PORT
|
||||
Frontend Port: $FRONTEND_PORT
|
||||
========================================
|
||||
EOF
|
||||
|
||||
echo ""
|
||||
|
||||
# ============================================
|
||||
# START BACKEND
|
||||
# ============================================
|
||||
echo "📡 Starting Backend (FastAPI + Socket.io)..."
|
||||
cd "$SCRIPT_DIR/backend"
|
||||
uv run python -m app.main > "$LOG_DIR/backend.log" 2>&1 &
|
||||
BACKEND_PID=$!
|
||||
echo " Backend started with PID: $BACKEND_PID"
|
||||
echo " Logs: $LOG_DIR/backend.log"
|
||||
echo " API: http://localhost:8000"
|
||||
echo "$BACKEND_PID" > "$LOG_DIR/backend.pid"
|
||||
echo " PID: $BACKEND_PID"
|
||||
echo " Log: $LOG_DIR/backend.log"
|
||||
|
||||
# Health check with timeout
|
||||
echo " Waiting for backend to be ready..."
|
||||
HEALTH_TIMEOUT=30
|
||||
HEALTH_COUNT=0
|
||||
BACKEND_READY=false
|
||||
|
||||
while [ $HEALTH_COUNT -lt $HEALTH_TIMEOUT ]; do
|
||||
# Check if process is still running
|
||||
if ! ps -p $BACKEND_PID > /dev/null 2>&1; then
|
||||
echo ""
|
||||
echo "❌ Backend process died during startup!"
|
||||
echo " Check logs: tail -50 $LOG_DIR/backend.log"
|
||||
tail -20 "$LOG_DIR/backend.log" 2>/dev/null || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check health endpoint
|
||||
if curl -s http://$HEALTH_CHECK_HOST:$BACKEND_PORT/health > /dev/null 2>&1; then
|
||||
BACKEND_READY=true
|
||||
break
|
||||
fi
|
||||
|
||||
# Also accept root endpoint as fallback
|
||||
if curl -s http://$HEALTH_CHECK_HOST:$BACKEND_PORT/ > /dev/null 2>&1; then
|
||||
BACKEND_READY=true
|
||||
break
|
||||
fi
|
||||
|
||||
sleep 1
|
||||
HEALTH_COUNT=$((HEALTH_COUNT + 1))
|
||||
printf "."
|
||||
done
|
||||
|
||||
echo ""
|
||||
|
||||
# Wait for backend to initialize
|
||||
sleep 3
|
||||
if [ "$BACKEND_READY" = true ]; then
|
||||
echo " ✓ Backend ready (${HEALTH_COUNT}s)"
|
||||
echo " URL: http://localhost:$BACKEND_PORT"
|
||||
else
|
||||
echo " ⚠️ Backend health check timed out after ${HEALTH_TIMEOUT}s"
|
||||
echo " Backend may still be starting. Check logs if issues occur."
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# ============================================
|
||||
# START FRONTEND
|
||||
# ============================================
|
||||
echo "🎨 Starting Frontend (Nuxt 3 - $FRONTEND_TYPE)..."
|
||||
cd "$FRONTEND_DIR"
|
||||
|
||||
# Set environment variables based on mode
|
||||
if [ "$ENV_MODE" = "dev" ]; then
|
||||
echo " Mode: Development (localhost)"
|
||||
export NUXT_PUBLIC_API_URL="http://localhost:$BACKEND_PORT"
|
||||
export NUXT_PUBLIC_WS_URL="http://localhost:$BACKEND_PORT"
|
||||
export NUXT_PUBLIC_DISCORD_REDIRECT_URI="http://localhost:$FRONTEND_PORT/auth/callback"
|
||||
elif [ "$ENV_MODE" = "prod" ]; then
|
||||
echo " Mode: Production (using .env file)"
|
||||
# Load .env file if it exists (Nuxt will use these)
|
||||
if [ -f ".env" ]; then
|
||||
# Show what URLs will be used
|
||||
API_URL=$(grep "^NUXT_PUBLIC_API_URL=" .env 2>/dev/null | cut -d= -f2 || echo "not set")
|
||||
echo " API URL: $API_URL"
|
||||
else
|
||||
echo " ⚠️ No .env file found - using Nuxt defaults"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Start Frontend
|
||||
echo "🎨 Starting Frontend (Nuxt 3)..."
|
||||
cd "$SCRIPT_DIR/frontend-sba"
|
||||
npm run dev > "$LOG_DIR/frontend.log" 2>&1 &
|
||||
FRONTEND_PID=$!
|
||||
echo " Frontend started with PID: $FRONTEND_PID"
|
||||
echo " Logs: $LOG_DIR/frontend.log"
|
||||
echo " URL: http://localhost:3000"
|
||||
echo ""
|
||||
|
||||
# Save PIDs for stop script
|
||||
echo "$BACKEND_PID" > "$LOG_DIR/backend.pid"
|
||||
echo "$FRONTEND_PID" > "$LOG_DIR/frontend.pid"
|
||||
echo " PID: $FRONTEND_PID"
|
||||
echo " Log: $LOG_DIR/frontend.log"
|
||||
|
||||
# Wait for frontend to be ready
|
||||
echo " Waiting for frontend to be ready..."
|
||||
FRONTEND_TIMEOUT=60
|
||||
FRONTEND_COUNT=0
|
||||
FRONTEND_READY=false
|
||||
|
||||
while [ $FRONTEND_COUNT -lt $FRONTEND_TIMEOUT ]; do
|
||||
# Check if process is still running
|
||||
if ! ps -p $FRONTEND_PID > /dev/null 2>&1; then
|
||||
echo ""
|
||||
echo "❌ Frontend process died during startup!"
|
||||
echo " Check logs: tail -50 $LOG_DIR/frontend.log"
|
||||
tail -20 "$LOG_DIR/frontend.log" 2>/dev/null || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if frontend is responding
|
||||
if curl -s http://$HEALTH_CHECK_HOST:$FRONTEND_PORT > /dev/null 2>&1; then
|
||||
FRONTEND_READY=true
|
||||
break
|
||||
fi
|
||||
|
||||
sleep 1
|
||||
FRONTEND_COUNT=$((FRONTEND_COUNT + 1))
|
||||
printf "."
|
||||
done
|
||||
|
||||
echo "✅ Services started successfully!"
|
||||
echo ""
|
||||
echo "📊 To view logs:"
|
||||
echo " Backend: tail -f $LOG_DIR/backend.log"
|
||||
echo " Frontend: tail -f $LOG_DIR/frontend.log"
|
||||
|
||||
if [ "$FRONTEND_READY" = true ]; then
|
||||
echo " ✓ Frontend ready (${FRONTEND_COUNT}s)"
|
||||
echo " URL: http://localhost:$FRONTEND_PORT"
|
||||
else
|
||||
echo " ⚠️ Frontend health check timed out after ${FRONTEND_TIMEOUT}s"
|
||||
echo " Frontend may still be compiling. Check logs if issues occur."
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# ============================================
|
||||
# SUMMARY
|
||||
# ============================================
|
||||
echo "========================================"
|
||||
echo "✅ Services Started Successfully!"
|
||||
echo "========================================"
|
||||
echo ""
|
||||
echo "📊 Service Status:"
|
||||
echo " Backend: http://localhost:$BACKEND_PORT (PID: $BACKEND_PID)"
|
||||
echo " Frontend: http://localhost:$FRONTEND_PORT (PID: $FRONTEND_PID)"
|
||||
echo ""
|
||||
|
||||
# Show API URL based on mode
|
||||
if [ "$ENV_MODE" = "dev" ]; then
|
||||
echo "🔗 API Configuration (dev mode):"
|
||||
echo " API URL: http://localhost:$BACKEND_PORT"
|
||||
echo " WS URL: http://localhost:$BACKEND_PORT"
|
||||
elif [ "$ENV_MODE" = "prod" ]; then
|
||||
echo "🔗 API Configuration (prod mode):"
|
||||
if [ -f "$FRONTEND_DIR/.env" ]; then
|
||||
grep "^NUXT_PUBLIC_API_URL=" "$FRONTEND_DIR/.env" 2>/dev/null | sed 's/^/ /' || true
|
||||
grep "^NUXT_PUBLIC_WS_URL=" "$FRONTEND_DIR/.env" 2>/dev/null | sed 's/^/ /' || true
|
||||
fi
|
||||
fi
|
||||
echo ""
|
||||
|
||||
echo "📋 Quick Commands:"
|
||||
echo " View logs: tail -f $LOG_DIR/backend.log"
|
||||
echo " tail -f $LOG_DIR/frontend.log"
|
||||
echo " Check status: ./status-services.sh"
|
||||
echo " Stop: ./stop-services.sh"
|
||||
echo " Restart: ./stop-services.sh && ./start-services.sh"
|
||||
echo ""
|
||||
echo "📌 Running: $GIT_BRANCH @ $GIT_COMMIT$GIT_DIRTY ($ENV_MODE mode)"
|
||||
echo ""
|
||||
echo "🛑 To stop services: ./stop-services.sh"
|
||||
|
||||
275
status-services.sh
Executable file
275
status-services.sh
Executable file
@ -0,0 +1,275 @@
|
||||
#!/bin/bash
|
||||
# Check status of backend and frontend services
|
||||
# Shows running state, health, ports, and version info
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
LOG_DIR="$SCRIPT_DIR/logs"
|
||||
BACKEND_PORT=8000
|
||||
FRONTEND_PORT=3000
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Parse arguments
|
||||
WATCH_MODE=false
|
||||
JSON_OUTPUT=false
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--watch|-w)
|
||||
WATCH_MODE=true
|
||||
shift
|
||||
;;
|
||||
--json|-j)
|
||||
JSON_OUTPUT=true
|
||||
shift
|
||||
;;
|
||||
--help|-h)
|
||||
echo "Usage: $0 [OPTIONS]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --watch, -w Continuously monitor (refresh every 2s)"
|
||||
echo " --json, -j Output in JSON format"
|
||||
echo " --help, -h Show this help message"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Function to check if a port is in use and get the PID
|
||||
check_port() {
|
||||
local port=$1
|
||||
lsof -ti :"$port" 2>/dev/null | head -1
|
||||
}
|
||||
|
||||
# Function to check HTTP health
|
||||
check_health() {
|
||||
local url=$1
|
||||
local timeout=${2:-2}
|
||||
if curl -s --max-time "$timeout" "$url" > /dev/null 2>&1; then
|
||||
echo "healthy"
|
||||
else
|
||||
echo "unhealthy"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to get process uptime
|
||||
get_uptime() {
|
||||
local pid=$1
|
||||
if [ -n "$pid" ] && ps -p "$pid" > /dev/null 2>&1; then
|
||||
ps -p "$pid" -o etime= 2>/dev/null | xargs
|
||||
else
|
||||
echo "N/A"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to get memory usage
|
||||
get_memory() {
|
||||
local pid=$1
|
||||
if [ -n "$pid" ] && ps -p "$pid" > /dev/null 2>&1; then
|
||||
ps -p "$pid" -o rss= 2>/dev/null | awk '{printf "%.1f MB", $1/1024}'
|
||||
else
|
||||
echo "N/A"
|
||||
fi
|
||||
}
|
||||
|
||||
# Main status check function
|
||||
check_status() {
|
||||
# Get PIDs from files
|
||||
BACKEND_PID_FILE=""
|
||||
FRONTEND_PID_FILE=""
|
||||
|
||||
if [ -f "$LOG_DIR/backend.pid" ]; then
|
||||
BACKEND_PID_FILE=$(cat "$LOG_DIR/backend.pid")
|
||||
fi
|
||||
|
||||
if [ -f "$LOG_DIR/frontend.pid" ]; then
|
||||
FRONTEND_PID_FILE=$(cat "$LOG_DIR/frontend.pid")
|
||||
fi
|
||||
|
||||
# Check actual running processes
|
||||
BACKEND_PID_PORT=$(check_port $BACKEND_PORT)
|
||||
FRONTEND_PID_PORT=$(check_port $FRONTEND_PORT)
|
||||
|
||||
# Determine backend status
|
||||
BACKEND_RUNNING=false
|
||||
BACKEND_PID=""
|
||||
if [ -n "$BACKEND_PID_FILE" ] && ps -p "$BACKEND_PID_FILE" > /dev/null 2>&1; then
|
||||
BACKEND_RUNNING=true
|
||||
BACKEND_PID="$BACKEND_PID_FILE"
|
||||
elif [ -n "$BACKEND_PID_PORT" ]; then
|
||||
BACKEND_RUNNING=true
|
||||
BACKEND_PID="$BACKEND_PID_PORT"
|
||||
fi
|
||||
|
||||
# Determine frontend status
|
||||
FRONTEND_RUNNING=false
|
||||
FRONTEND_PID=""
|
||||
if [ -n "$FRONTEND_PID_FILE" ] && ps -p "$FRONTEND_PID_FILE" > /dev/null 2>&1; then
|
||||
FRONTEND_RUNNING=true
|
||||
FRONTEND_PID="$FRONTEND_PID_FILE"
|
||||
elif [ -n "$FRONTEND_PID_PORT" ]; then
|
||||
FRONTEND_RUNNING=true
|
||||
FRONTEND_PID="$FRONTEND_PID_PORT"
|
||||
fi
|
||||
|
||||
# Check health
|
||||
BACKEND_HEALTH="stopped"
|
||||
FRONTEND_HEALTH="stopped"
|
||||
|
||||
if [ "$BACKEND_RUNNING" = true ]; then
|
||||
BACKEND_HEALTH=$(check_health "http://localhost:$BACKEND_PORT/health")
|
||||
if [ "$BACKEND_HEALTH" = "unhealthy" ]; then
|
||||
# Try root endpoint as fallback
|
||||
BACKEND_HEALTH=$(check_health "http://localhost:$BACKEND_PORT/")
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$FRONTEND_RUNNING" = true ]; then
|
||||
FRONTEND_HEALTH=$(check_health "http://localhost:$FRONTEND_PORT")
|
||||
fi
|
||||
|
||||
# Get version info from startup log
|
||||
GIT_COMMIT="unknown"
|
||||
GIT_BRANCH="unknown"
|
||||
START_TIME="unknown"
|
||||
ENV_MODE="unknown"
|
||||
|
||||
if [ -f "$LOG_DIR/startup.log" ]; then
|
||||
GIT_COMMIT=$(grep "Git Commit:" "$LOG_DIR/startup.log" 2>/dev/null | cut -d: -f2 | xargs || echo "unknown")
|
||||
GIT_BRANCH=$(grep "Git Branch:" "$LOG_DIR/startup.log" 2>/dev/null | cut -d: -f2 | xargs || echo "unknown")
|
||||
START_TIME=$(grep "Timestamp:" "$LOG_DIR/startup.log" 2>/dev/null | cut -d: -f2- | xargs || echo "unknown")
|
||||
ENV_MODE=$(grep "Environment:" "$LOG_DIR/startup.log" 2>/dev/null | cut -d: -f2 | xargs || echo "unknown")
|
||||
fi
|
||||
|
||||
if [ "$JSON_OUTPUT" = true ]; then
|
||||
# JSON output
|
||||
cat << EOF
|
||||
{
|
||||
"backend": {
|
||||
"running": $BACKEND_RUNNING,
|
||||
"pid": ${BACKEND_PID:-null},
|
||||
"port": $BACKEND_PORT,
|
||||
"health": "$BACKEND_HEALTH",
|
||||
"uptime": "$(get_uptime "$BACKEND_PID")",
|
||||
"memory": "$(get_memory "$BACKEND_PID")"
|
||||
},
|
||||
"frontend": {
|
||||
"running": $FRONTEND_RUNNING,
|
||||
"pid": ${FRONTEND_PID:-null},
|
||||
"port": $FRONTEND_PORT,
|
||||
"health": "$FRONTEND_HEALTH",
|
||||
"uptime": "$(get_uptime "$FRONTEND_PID")",
|
||||
"memory": "$(get_memory "$FRONTEND_PID")"
|
||||
},
|
||||
"version": {
|
||||
"branch": "$GIT_BRANCH",
|
||||
"commit": "$GIT_COMMIT",
|
||||
"mode": "$ENV_MODE",
|
||||
"started": "$START_TIME"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
else
|
||||
# Human-readable output
|
||||
clear 2>/dev/null || true
|
||||
|
||||
echo "========================================"
|
||||
echo "📊 SBA Gameplay Services Status"
|
||||
echo "========================================"
|
||||
echo ""
|
||||
|
||||
# Backend status
|
||||
echo -n "📡 Backend: "
|
||||
if [ "$BACKEND_RUNNING" = true ]; then
|
||||
if [ "$BACKEND_HEALTH" = "healthy" ]; then
|
||||
echo -e "${GREEN}● Running${NC} (healthy)"
|
||||
else
|
||||
echo -e "${YELLOW}● Running${NC} (unhealthy)"
|
||||
fi
|
||||
echo " PID: $BACKEND_PID"
|
||||
echo " Port: $BACKEND_PORT"
|
||||
echo " Uptime: $(get_uptime "$BACKEND_PID")"
|
||||
echo " Memory: $(get_memory "$BACKEND_PID")"
|
||||
echo " URL: http://localhost:$BACKEND_PORT"
|
||||
else
|
||||
echo -e "${RED}○ Stopped${NC}"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Frontend status
|
||||
echo -n "🎨 Frontend: "
|
||||
if [ "$FRONTEND_RUNNING" = true ]; then
|
||||
if [ "$FRONTEND_HEALTH" = "healthy" ]; then
|
||||
echo -e "${GREEN}● Running${NC} (healthy)"
|
||||
else
|
||||
echo -e "${YELLOW}● Running${NC} (unhealthy)"
|
||||
fi
|
||||
echo " PID: $FRONTEND_PID"
|
||||
echo " Port: $FRONTEND_PORT"
|
||||
echo " Uptime: $(get_uptime "$FRONTEND_PID")"
|
||||
echo " Memory: $(get_memory "$FRONTEND_PID")"
|
||||
echo " URL: http://localhost:$FRONTEND_PORT"
|
||||
else
|
||||
echo -e "${RED}○ Stopped${NC}"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Version info
|
||||
echo "📌 Version:"
|
||||
echo " Branch: $GIT_BRANCH"
|
||||
echo " Commit: $GIT_COMMIT"
|
||||
echo " Mode: $ENV_MODE"
|
||||
echo " Started: $START_TIME"
|
||||
echo ""
|
||||
|
||||
# Overall status
|
||||
if [ "$BACKEND_RUNNING" = true ] && [ "$FRONTEND_RUNNING" = true ]; then
|
||||
if [ "$BACKEND_HEALTH" = "healthy" ] && [ "$FRONTEND_HEALTH" = "healthy" ]; then
|
||||
echo -e "${GREEN}✅ All services healthy${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}⚠️ Some services unhealthy${NC}"
|
||||
fi
|
||||
elif [ "$BACKEND_RUNNING" = true ] || [ "$FRONTEND_RUNNING" = true ]; then
|
||||
echo -e "${YELLOW}⚠️ Partial services running${NC}"
|
||||
else
|
||||
echo -e "${RED}❌ All services stopped${NC}"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Quick commands
|
||||
echo "📋 Commands:"
|
||||
if [ "$BACKEND_RUNNING" = false ] || [ "$FRONTEND_RUNNING" = false ]; then
|
||||
echo " Start: ./start-services.sh"
|
||||
fi
|
||||
if [ "$BACKEND_RUNNING" = true ] || [ "$FRONTEND_RUNNING" = true ]; then
|
||||
echo " Stop: ./stop-services.sh"
|
||||
echo " Restart: ./stop-services.sh && ./start-services.sh"
|
||||
fi
|
||||
echo " Logs: tail -f $LOG_DIR/backend.log"
|
||||
echo ""
|
||||
|
||||
if [ "$WATCH_MODE" = true ]; then
|
||||
echo -e "${BLUE}[Refreshing every 2s - Press Ctrl+C to exit]${NC}"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Main execution
|
||||
if [ "$WATCH_MODE" = true ]; then
|
||||
# Watch mode - refresh every 2 seconds
|
||||
while true; do
|
||||
check_status
|
||||
sleep 2
|
||||
done
|
||||
else
|
||||
check_status
|
||||
fi
|
||||
294
stop-services.sh
294
stop-services.sh
@ -1,12 +1,52 @@
|
||||
#!/bin/bash
|
||||
# Stop both backend and frontend services
|
||||
# Enhanced to kill entire process trees and clean up orphans
|
||||
# Enhanced to kill entire process trees, clean up orphans, and verify shutdown
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
LOG_DIR="$SCRIPT_DIR/logs"
|
||||
BACKEND_PORT=8000
|
||||
FRONTEND_PORT=3000
|
||||
|
||||
echo "🛑 Stopping SBA Gameplay Services..."
|
||||
echo ""
|
||||
# Parse arguments
|
||||
QUIET_MODE=false
|
||||
FORCE_MODE=false
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--quiet|-q)
|
||||
QUIET_MODE=true
|
||||
shift
|
||||
;;
|
||||
--force|-f)
|
||||
FORCE_MODE=true
|
||||
shift
|
||||
;;
|
||||
--help|-h)
|
||||
echo "Usage: $0 [OPTIONS]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --quiet, -q Minimal output"
|
||||
echo " --force, -f Skip graceful shutdown, kill immediately"
|
||||
echo " --help, -h Show this help message"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
log() {
|
||||
if [ "$QUIET_MODE" = false ]; then
|
||||
echo "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
log "========================================"
|
||||
log "🛑 Stopping SBA Gameplay Services"
|
||||
log "========================================"
|
||||
log ""
|
||||
|
||||
# Function to kill process tree
|
||||
kill_tree() {
|
||||
@ -16,7 +56,7 @@ kill_tree() {
|
||||
# Get all child PIDs
|
||||
local children=$(pgrep -P "$pid" 2>/dev/null || true)
|
||||
|
||||
# Kill children first
|
||||
# Kill children first (depth-first)
|
||||
for child in $children; do
|
||||
kill_tree "$child" "$sig"
|
||||
done
|
||||
@ -27,87 +67,211 @@ kill_tree() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Stop Backend
|
||||
if [ -f "$LOG_DIR/backend.pid" ]; then
|
||||
BACKEND_PID=$(cat "$LOG_DIR/backend.pid")
|
||||
if ps -p "$BACKEND_PID" > /dev/null 2>&1; then
|
||||
echo "📡 Stopping Backend (PID: $BACKEND_PID)..."
|
||||
kill_tree "$BACKEND_PID" TERM
|
||||
sleep 1
|
||||
# Force kill if still running
|
||||
if ps -p "$BACKEND_PID" > /dev/null 2>&1; then
|
||||
kill_tree "$BACKEND_PID" KILL
|
||||
# Function to stop a service gracefully
|
||||
stop_service() {
|
||||
local name=$1
|
||||
local pid_file=$2
|
||||
local icon=$3
|
||||
|
||||
if [ -f "$pid_file" ]; then
|
||||
local pid=$(cat "$pid_file")
|
||||
if ps -p "$pid" > /dev/null 2>&1; then
|
||||
log "$icon Stopping $name (PID: $pid)..."
|
||||
|
||||
if [ "$FORCE_MODE" = true ]; then
|
||||
# Force mode: kill immediately
|
||||
kill_tree "$pid" KILL
|
||||
log " ✓ $name killed (force mode)"
|
||||
else
|
||||
# Graceful mode: SIGTERM first, then SIGKILL
|
||||
kill_tree "$pid" TERM
|
||||
|
||||
# Wait up to 5 seconds for graceful shutdown
|
||||
local wait_count=0
|
||||
while [ $wait_count -lt 5 ]; do
|
||||
if ! ps -p "$pid" > /dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
wait_count=$((wait_count + 1))
|
||||
done
|
||||
|
||||
# Force kill if still running
|
||||
if ps -p "$pid" > /dev/null 2>&1; then
|
||||
log " → Graceful shutdown timed out, forcing..."
|
||||
kill_tree "$pid" KILL
|
||||
sleep 1
|
||||
fi
|
||||
|
||||
if ps -p "$pid" > /dev/null 2>&1; then
|
||||
log " ⚠️ $name may still be running"
|
||||
else
|
||||
log " ✓ $name stopped"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
log " ⚠️ $name process not found (stale PID file)"
|
||||
fi
|
||||
echo " ✓ Backend stopped"
|
||||
rm -f "$pid_file"
|
||||
else
|
||||
echo " ⚠ Backend process not found"
|
||||
log " ℹ️ No $name PID file found"
|
||||
fi
|
||||
rm -f "$LOG_DIR/backend.pid"
|
||||
else
|
||||
echo " ⚠ No backend PID file found"
|
||||
fi
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Stop Backend
|
||||
stop_service "Backend" "$LOG_DIR/backend.pid" "📡"
|
||||
log ""
|
||||
|
||||
# Stop Frontend
|
||||
if [ -f "$LOG_DIR/frontend.pid" ]; then
|
||||
FRONTEND_PID=$(cat "$LOG_DIR/frontend.pid")
|
||||
if ps -p "$FRONTEND_PID" > /dev/null 2>&1; then
|
||||
echo "🎨 Stopping Frontend (PID: $FRONTEND_PID)..."
|
||||
kill_tree "$FRONTEND_PID" TERM
|
||||
sleep 1
|
||||
# Force kill if still running
|
||||
if ps -p "$FRONTEND_PID" > /dev/null 2>&1; then
|
||||
kill_tree "$FRONTEND_PID" KILL
|
||||
fi
|
||||
echo " ✓ Frontend stopped"
|
||||
else
|
||||
echo " ⚠ Frontend process not found"
|
||||
fi
|
||||
rm -f "$LOG_DIR/frontend.pid"
|
||||
else
|
||||
echo " ⚠ No frontend PID file found"
|
||||
fi
|
||||
echo ""
|
||||
stop_service "Frontend" "$LOG_DIR/frontend.pid" "🎨"
|
||||
log ""
|
||||
|
||||
# Aggressive cleanup: kill ALL related processes by pattern matching
|
||||
echo "🔍 Checking for any remaining processes..."
|
||||
# ============================================
|
||||
# AGGRESSIVE CLEANUP: Kill orphaned processes
|
||||
# ============================================
|
||||
log "🔍 Checking for orphaned processes..."
|
||||
|
||||
# Kill all backend processes for this app (uvicorn OR python -m app.main)
|
||||
BACKEND_PIDS=$(pgrep -f "python.*app\.main" 2>/dev/null || true)
|
||||
UVICORN_PIDS=$(pgrep -f "uvicorn.*app\.main" 2>/dev/null || true)
|
||||
ALL_BACKEND_PIDS="$BACKEND_PIDS $UVICORN_PIDS"
|
||||
ALL_BACKEND_PIDS=$(echo "$ALL_BACKEND_PIDS" | tr ' ' '\n' | sort -u | tr '\n' ' ' | xargs)
|
||||
ORPHANS_FOUND=false
|
||||
|
||||
# Kill all backend processes for this specific app
|
||||
# Use more specific pattern to avoid killing unrelated processes
|
||||
BACKEND_PATTERN="python.*app\.main"
|
||||
BACKEND_PIDS=$(pgrep -f "$BACKEND_PATTERN" 2>/dev/null || true)
|
||||
|
||||
# Also check for uvicorn processes
|
||||
UVICORN_PATTERN="uvicorn.*app\.main"
|
||||
UVICORN_PIDS=$(pgrep -f "$UVICORN_PATTERN" 2>/dev/null || true)
|
||||
|
||||
# Combine and deduplicate
|
||||
ALL_BACKEND_PIDS=$(echo "$BACKEND_PIDS $UVICORN_PIDS" | tr ' ' '\n' | sort -u | tr '\n' ' ' | xargs)
|
||||
|
||||
if [ -n "$ALL_BACKEND_PIDS" ]; then
|
||||
echo " Found orphaned backend processes: $ALL_BACKEND_PIDS"
|
||||
ORPHANS_FOUND=true
|
||||
log " Found orphaned backend processes: $ALL_BACKEND_PIDS"
|
||||
for pid in $ALL_BACKEND_PIDS; do
|
||||
kill_tree "$pid" KILL
|
||||
done
|
||||
echo " ✓ Killed orphaned backend processes"
|
||||
log " ✓ Killed orphaned backend processes"
|
||||
fi
|
||||
|
||||
# Also kill any processes on port 8000
|
||||
PORT_8000_PIDS=$(lsof -ti :8000 2>/dev/null || true)
|
||||
if [ -n "$PORT_8000_PIDS" ]; then
|
||||
echo " Found processes on port 8000: $PORT_8000_PIDS"
|
||||
for pid in $PORT_8000_PIDS; do
|
||||
# Kill processes on backend port
|
||||
PORT_BACKEND_PIDS=$(lsof -ti :$BACKEND_PORT 2>/dev/null || true)
|
||||
if [ -n "$PORT_BACKEND_PIDS" ]; then
|
||||
ORPHANS_FOUND=true
|
||||
log " Found processes on port $BACKEND_PORT: $PORT_BACKEND_PIDS"
|
||||
for pid in $PORT_BACKEND_PIDS; do
|
||||
kill -9 "$pid" 2>/dev/null || true
|
||||
done
|
||||
echo " ✓ Killed processes on port 8000"
|
||||
log " ✓ Killed processes on port $BACKEND_PORT"
|
||||
fi
|
||||
|
||||
# Kill all nuxt dev processes in this directory
|
||||
FRONTEND_PIDS=$(pgrep -f "nuxt.*dev" | while read pid; do
|
||||
if ps -p $pid -o args= | grep -q "$SCRIPT_DIR/frontend-sba"; then
|
||||
echo $pid
|
||||
# Kill processes on frontend port
|
||||
PORT_FRONTEND_PIDS=$(lsof -ti :$FRONTEND_PORT 2>/dev/null || true)
|
||||
if [ -n "$PORT_FRONTEND_PIDS" ]; then
|
||||
ORPHANS_FOUND=true
|
||||
log " Found processes on port $FRONTEND_PORT: $PORT_FRONTEND_PIDS"
|
||||
for pid in $PORT_FRONTEND_PIDS; do
|
||||
kill -9 "$pid" 2>/dev/null || true
|
||||
done
|
||||
log " ✓ Killed processes on port $FRONTEND_PORT"
|
||||
fi
|
||||
|
||||
# Kill nuxt dev processes specifically for this project
|
||||
# Check if process command line contains our project path
|
||||
NUXT_PIDS=""
|
||||
for pid in $(pgrep -f "nuxt.*dev" 2>/dev/null || true); do
|
||||
# Verify this is for our project by checking cwd or command
|
||||
if ps -p "$pid" -o args= 2>/dev/null | grep -q "$SCRIPT_DIR" 2>/dev/null; then
|
||||
NUXT_PIDS="$NUXT_PIDS $pid"
|
||||
fi
|
||||
done)
|
||||
if [ -n "$FRONTEND_PIDS" ]; then
|
||||
echo " Found orphaned frontend processes: $FRONTEND_PIDS"
|
||||
for pid in $FRONTEND_PIDS; do
|
||||
done
|
||||
NUXT_PIDS=$(echo "$NUXT_PIDS" | xargs)
|
||||
|
||||
if [ -n "$NUXT_PIDS" ]; then
|
||||
ORPHANS_FOUND=true
|
||||
log " Found orphaned frontend processes: $NUXT_PIDS"
|
||||
for pid in $NUXT_PIDS; do
|
||||
kill_tree "$pid" KILL
|
||||
done
|
||||
echo " ✓ Killed orphaned frontend processes"
|
||||
log " ✓ Killed orphaned frontend processes"
|
||||
fi
|
||||
|
||||
echo "✅ Services stopped successfully!"
|
||||
# Kill any node processes that might be related to our frontend
|
||||
# Be more conservative here - only kill if definitely ours
|
||||
NODE_PIDS=""
|
||||
for pid in $(pgrep -f "node.*$SCRIPT_DIR/frontend" 2>/dev/null || true); do
|
||||
NODE_PIDS="$NODE_PIDS $pid"
|
||||
done
|
||||
NODE_PIDS=$(echo "$NODE_PIDS" | xargs)
|
||||
|
||||
if [ -n "$NODE_PIDS" ]; then
|
||||
ORPHANS_FOUND=true
|
||||
log " Found orphaned node processes: $NODE_PIDS"
|
||||
for pid in $NODE_PIDS; do
|
||||
kill -9 "$pid" 2>/dev/null || true
|
||||
done
|
||||
log " ✓ Killed orphaned node processes"
|
||||
fi
|
||||
|
||||
if [ "$ORPHANS_FOUND" = false ]; then
|
||||
log " ✓ No orphaned processes found"
|
||||
fi
|
||||
|
||||
log ""
|
||||
|
||||
# ============================================
|
||||
# VERIFICATION: Confirm services are stopped
|
||||
# ============================================
|
||||
log "🔍 Verification..."
|
||||
|
||||
# Give processes a moment to fully release ports
|
||||
sleep 1
|
||||
|
||||
VERIFICATION_OK=true
|
||||
|
||||
# Check backend port
|
||||
if lsof -ti :$BACKEND_PORT > /dev/null 2>&1; then
|
||||
log " ⚠️ Port $BACKEND_PORT still in use!"
|
||||
VERIFICATION_OK=false
|
||||
else
|
||||
log " ✓ Port $BACKEND_PORT is free"
|
||||
fi
|
||||
|
||||
# Check frontend port
|
||||
if lsof -ti :$FRONTEND_PORT > /dev/null 2>&1; then
|
||||
log " ⚠️ Port $FRONTEND_PORT still in use!"
|
||||
VERIFICATION_OK=false
|
||||
else
|
||||
log " ✓ Port $FRONTEND_PORT is free"
|
||||
fi
|
||||
|
||||
# Check for any remaining processes
|
||||
REMAINING_BACKEND=$(pgrep -f "$BACKEND_PATTERN" 2>/dev/null || true)
|
||||
if [ -n "$REMAINING_BACKEND" ]; then
|
||||
log " ⚠️ Backend processes still running: $REMAINING_BACKEND"
|
||||
VERIFICATION_OK=false
|
||||
fi
|
||||
|
||||
log ""
|
||||
|
||||
# ============================================
|
||||
# SUMMARY
|
||||
# ============================================
|
||||
if [ "$VERIFICATION_OK" = true ]; then
|
||||
log "========================================"
|
||||
log "✅ Services Stopped Successfully!"
|
||||
log "========================================"
|
||||
else
|
||||
log "========================================"
|
||||
log "⚠️ Services Stopped (with warnings)"
|
||||
log "========================================"
|
||||
log ""
|
||||
log "Some processes may still be running. Try:"
|
||||
log " $0 --force"
|
||||
log ""
|
||||
log "Or manually check:"
|
||||
log " lsof -ti :$BACKEND_PORT"
|
||||
log " lsof -ti :$FRONTEND_PORT"
|
||||
fi
|
||||
|
||||
log ""
|
||||
|
||||
Loading…
Reference in New Issue
Block a user