mirror of
https://github.com/Cccc-owo/CheckInApp.git
synced 2026-06-17 05:56:29 +00:00
fdc725b893
backend & frontend
633 lines
17 KiB
Bash
633 lines
17 KiB
Bash
#!/bin/bash
|
|
# ==============================================================================
|
|
# CheckIn App V2 - Unified Process Manager (Linux/Mac)
|
|
# Usage: ./manage.sh {start|stop|restart|status|log} [backend|frontend|all]
|
|
# ==============================================================================
|
|
|
|
set -e
|
|
|
|
# Get script directory
|
|
APP_DIR=$(cd "$(dirname "$0")" && pwd)
|
|
|
|
# Configuration
|
|
VENV_DIR="$APP_DIR/venv"
|
|
BACKEND_PID_FILE="$APP_DIR/backend.pid"
|
|
FRONTEND_PID_FILE="$APP_DIR/frontend.pid"
|
|
BACKEND_LOG_FILE="$APP_DIR/logs/backend.log"
|
|
FRONTEND_LOG_FILE="$APP_DIR/logs/frontend.log"
|
|
PYTHON_EXE="$VENV_DIR/bin/python"
|
|
|
|
# Parse command and target
|
|
COMMAND=$1
|
|
TARGET=${2:-all}
|
|
|
|
# Color codes for better output
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
RED='\033[0;31m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Helper functions
|
|
log_info() {
|
|
echo -e "${GREEN}[INFO]${NC} $1"
|
|
}
|
|
|
|
log_warn() {
|
|
echo -e "${YELLOW}[WARNING]${NC} $1"
|
|
}
|
|
|
|
log_error() {
|
|
echo -e "${RED}[ERROR]${NC} $1"
|
|
}
|
|
|
|
log_ok() {
|
|
echo -e "${GREEN}[OK]${NC} $1"
|
|
}
|
|
|
|
# ============================================
|
|
# START COMMAND
|
|
# ============================================
|
|
start_command() {
|
|
case $TARGET in
|
|
backend)
|
|
echo "========================================"
|
|
echo "CheckIn App V2 - Starting Backend"
|
|
echo "========================================"
|
|
echo ""
|
|
start_backend
|
|
;;
|
|
frontend)
|
|
echo "========================================"
|
|
echo "CheckIn App V2 - Starting Frontend"
|
|
echo "========================================"
|
|
echo ""
|
|
start_frontend
|
|
;;
|
|
all)
|
|
echo "========================================"
|
|
echo "CheckIn App V2 - Starting All Services"
|
|
echo "========================================"
|
|
echo ""
|
|
start_backend
|
|
echo ""
|
|
start_frontend
|
|
echo ""
|
|
echo "========================================"
|
|
echo "All Services Started!"
|
|
echo "========================================"
|
|
echo ""
|
|
echo "Backend API: http://localhost:8000"
|
|
echo "API Docs: http://localhost:8000/docs"
|
|
echo "Frontend App: http://localhost:3000"
|
|
echo ""
|
|
;;
|
|
*)
|
|
log_error "Invalid target: $TARGET"
|
|
usage
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Backend start logic
|
|
start_backend() {
|
|
# Check if already running
|
|
if [ -f "$BACKEND_PID_FILE" ]; then
|
|
PID=$(cat "$BACKEND_PID_FILE")
|
|
if ps -p $PID > /dev/null 2>&1; then
|
|
log_warn "Backend is already running (PID: $PID)"
|
|
return 0
|
|
else
|
|
log_info "Backend PID file exists but process not running, cleaning up..."
|
|
rm -f "$BACKEND_PID_FILE"
|
|
fi
|
|
fi
|
|
|
|
# Check virtual environment
|
|
if [ ! -d "$VENV_DIR" ]; then
|
|
log_error "Virtual environment does not exist: $VENV_DIR"
|
|
log_info "Please run first: python3 -m venv venv"
|
|
exit 1
|
|
fi
|
|
|
|
# Check required directories
|
|
mkdir -p data logs sessions
|
|
|
|
log_info "Starting backend service in background..."
|
|
|
|
# Start backend using run_daemon.py
|
|
nohup "$PYTHON_EXE" "$APP_DIR/run_daemon.py" > "$BACKEND_LOG_FILE" 2>&1 &
|
|
PID=$!
|
|
echo $PID > "$BACKEND_PID_FILE"
|
|
|
|
log_info "Waiting for backend to start..."
|
|
sleep 3
|
|
|
|
# Check if port 8000 is listening
|
|
SERVICE_RUNNING=0
|
|
for i in {1..10}; do
|
|
if lsof -i :8000 > /dev/null 2>&1 || netstat -tuln 2>/dev/null | grep -q :8000; then
|
|
SERVICE_RUNNING=1
|
|
break
|
|
fi
|
|
sleep 1
|
|
done
|
|
|
|
if [ $SERVICE_RUNNING -eq 1 ]; then
|
|
# Get actual PID from port 8000
|
|
ACTUAL_PID=$(lsof -ti :8000 2>/dev/null | head -n 1)
|
|
if [ -n "$ACTUAL_PID" ]; then
|
|
echo $ACTUAL_PID > "$BACKEND_PID_FILE"
|
|
log_ok "Backend started successfully (PID: $ACTUAL_PID)"
|
|
echo " API Docs: http://localhost:8000/docs"
|
|
echo " Log: $BACKEND_LOG_FILE"
|
|
else
|
|
log_ok "Backend started successfully (PID: $PID)"
|
|
echo " API Docs: http://localhost:8000/docs"
|
|
echo " Log: $BACKEND_LOG_FILE"
|
|
fi
|
|
else
|
|
log_error "Backend failed to start - port 8000 not listening"
|
|
log_info "Check log: $BACKEND_LOG_FILE"
|
|
echo ""
|
|
echo "[DEBUG] Last 10 lines of log:"
|
|
if [ -f "$BACKEND_LOG_FILE" ]; then
|
|
tail -n 10 "$BACKEND_LOG_FILE"
|
|
else
|
|
echo "Log file not found"
|
|
fi
|
|
rm -f "$BACKEND_PID_FILE"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Frontend start logic
|
|
start_frontend() {
|
|
# Check if already running
|
|
if [ -f "$FRONTEND_PID_FILE" ]; then
|
|
PID=$(cat "$FRONTEND_PID_FILE")
|
|
if ps -p $PID > /dev/null 2>&1; then
|
|
log_warn "Frontend is already running (PID: $PID)"
|
|
return 0
|
|
else
|
|
log_info "Frontend PID file exists but process not running, cleaning up..."
|
|
rm -f "$FRONTEND_PID_FILE"
|
|
fi
|
|
fi
|
|
|
|
# Check Node.js
|
|
if ! command -v node &> /dev/null; then
|
|
log_error "Node.js not found"
|
|
log_info "Please install Node.js from https://nodejs.org/"
|
|
exit 1
|
|
fi
|
|
|
|
# Check frontend directory
|
|
if [ ! -d "frontend" ]; then
|
|
log_error "Frontend directory not found"
|
|
exit 1
|
|
fi
|
|
|
|
# Check node_modules
|
|
if [ ! -d "frontend/node_modules" ]; then
|
|
log_info "Installing frontend dependencies..."
|
|
cd frontend
|
|
npm install
|
|
cd ..
|
|
fi
|
|
|
|
log_info "Starting frontend service in background..."
|
|
|
|
# Start frontend in background
|
|
cd frontend
|
|
nohup npm run dev > "$FRONTEND_LOG_FILE" 2>&1 &
|
|
PID=$!
|
|
cd ..
|
|
echo $PID > "$FRONTEND_PID_FILE"
|
|
|
|
log_info "Waiting for frontend to start..."
|
|
sleep 3
|
|
|
|
# Check if port 3000 is listening
|
|
SERVICE_RUNNING=0
|
|
for i in {1..10}; do
|
|
if lsof -i :3000 > /dev/null 2>&1 || netstat -tuln 2>/dev/null | grep -q :3000; then
|
|
SERVICE_RUNNING=1
|
|
break
|
|
fi
|
|
sleep 1
|
|
done
|
|
|
|
if [ $SERVICE_RUNNING -eq 1 ]; then
|
|
# Get actual PID from port 3000
|
|
ACTUAL_PID=$(lsof -ti :3000 2>/dev/null | head -n 1)
|
|
if [ -n "$ACTUAL_PID" ]; then
|
|
echo $ACTUAL_PID > "$FRONTEND_PID_FILE"
|
|
log_ok "Frontend started successfully (PID: $ACTUAL_PID)"
|
|
echo " URL: http://localhost:3000"
|
|
echo " Log: $FRONTEND_LOG_FILE"
|
|
else
|
|
log_ok "Frontend started successfully (PID: $PID)"
|
|
echo " URL: http://localhost:3000"
|
|
echo " Log: $FRONTEND_LOG_FILE"
|
|
fi
|
|
else
|
|
log_error "Frontend failed to start - port 3000 not listening"
|
|
log_info "Check log: $FRONTEND_LOG_FILE"
|
|
echo ""
|
|
echo "[DEBUG] Last 10 lines of log:"
|
|
if [ -f "$FRONTEND_LOG_FILE" ]; then
|
|
tail -n 10 "$FRONTEND_LOG_FILE"
|
|
else
|
|
echo "Log file not found"
|
|
fi
|
|
rm -f "$FRONTEND_PID_FILE"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# ============================================
|
|
# STOP COMMAND
|
|
# ============================================
|
|
stop_command() {
|
|
case $TARGET in
|
|
backend)
|
|
stop_backend
|
|
;;
|
|
frontend)
|
|
stop_frontend
|
|
;;
|
|
all)
|
|
echo "========================================"
|
|
echo "CheckIn App V2 - Stopping All Services"
|
|
echo "========================================"
|
|
echo ""
|
|
stop_backend
|
|
echo ""
|
|
stop_frontend
|
|
;;
|
|
*)
|
|
log_error "Invalid target: $TARGET"
|
|
usage
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Backend stop logic
|
|
stop_backend() {
|
|
log_info "Stopping backend..."
|
|
|
|
# First try to kill by port
|
|
BACKEND_KILLED=0
|
|
PIDS=$(lsof -ti :8000 2>/dev/null)
|
|
if [ -n "$PIDS" ]; then
|
|
for pid in $PIDS; do
|
|
kill -TERM $pid 2>/dev/null || kill -9 $pid 2>/dev/null
|
|
if [ $? -eq 0 ]; then
|
|
log_ok "Backend stopped (PID: $pid)"
|
|
BACKEND_KILLED=1
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# Then try PID file if port method didn't work
|
|
if [ $BACKEND_KILLED -eq 0 ]; then
|
|
if [ -f "$BACKEND_PID_FILE" ]; then
|
|
PID=$(cat "$BACKEND_PID_FILE")
|
|
if ps -p $PID > /dev/null 2>&1; then
|
|
kill -TERM $PID 2>/dev/null || kill -9 $PID 2>/dev/null
|
|
if [ $? -eq 0 ]; then
|
|
log_ok "Backend stopped (PID: $PID)"
|
|
fi
|
|
else
|
|
log_warn "Backend not running (process does not exist)"
|
|
fi
|
|
else
|
|
log_warn "Backend not running (no process found)"
|
|
fi
|
|
fi
|
|
|
|
# Clean up PID file
|
|
rm -f "$BACKEND_PID_FILE"
|
|
}
|
|
|
|
# Frontend stop logic
|
|
stop_frontend() {
|
|
log_info "Stopping frontend..."
|
|
|
|
# First try to kill by port
|
|
FRONTEND_KILLED=0
|
|
|
|
# Check port 3000
|
|
PIDS=$(lsof -ti :3000 2>/dev/null)
|
|
if [ -n "$PIDS" ]; then
|
|
for pid in $PIDS; do
|
|
kill -TERM $pid 2>/dev/null || kill -9 $pid 2>/dev/null
|
|
if [ $? -eq 0 ]; then
|
|
log_ok "Frontend stopped (PID: $pid)"
|
|
FRONTEND_KILLED=1
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# Also check ports 3001-3010 (Vite fallback ports)
|
|
if [ $FRONTEND_KILLED -eq 0 ]; then
|
|
for port in {3001..3010}; do
|
|
PIDS=$(lsof -ti :$port 2>/dev/null)
|
|
if [ -n "$PIDS" ]; then
|
|
for pid in $PIDS; do
|
|
# Check if it's a node process
|
|
if ps -p $pid -o comm= | grep -q node; then
|
|
kill -TERM $pid 2>/dev/null || kill -9 $pid 2>/dev/null
|
|
if [ $? -eq 0 ]; then
|
|
log_ok "Frontend stopped (PID: $pid, Port: $port)"
|
|
FRONTEND_KILLED=1
|
|
fi
|
|
fi
|
|
done
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# Then try PID file if port method didn't work
|
|
if [ $FRONTEND_KILLED -eq 0 ]; then
|
|
if [ -f "$FRONTEND_PID_FILE" ]; then
|
|
PID=$(cat "$FRONTEND_PID_FILE")
|
|
if ps -p $PID > /dev/null 2>&1; then
|
|
kill -TERM $PID 2>/dev/null || kill -9 $PID 2>/dev/null
|
|
if [ $? -eq 0 ]; then
|
|
log_ok "Frontend stopped (PID: $PID)"
|
|
fi
|
|
else
|
|
log_warn "Frontend not running (process does not exist)"
|
|
fi
|
|
else
|
|
log_warn "Frontend not running (no process found)"
|
|
fi
|
|
fi
|
|
|
|
# Clean up PID file
|
|
rm -f "$FRONTEND_PID_FILE"
|
|
}
|
|
|
|
# ============================================
|
|
# RESTART COMMAND
|
|
# ============================================
|
|
restart_command() {
|
|
log_info "Restarting $TARGET..."
|
|
echo ""
|
|
stop_command
|
|
sleep 2
|
|
start_command
|
|
}
|
|
|
|
# ============================================
|
|
# STATUS COMMAND
|
|
# ============================================
|
|
status_command() {
|
|
echo "========================================"
|
|
echo "CheckIn App V2 - Service Status"
|
|
echo "========================================"
|
|
echo ""
|
|
|
|
case $TARGET in
|
|
backend)
|
|
status_backend
|
|
;;
|
|
frontend)
|
|
status_frontend
|
|
;;
|
|
all)
|
|
status_backend
|
|
echo ""
|
|
status_frontend
|
|
;;
|
|
*)
|
|
log_error "Invalid target: $TARGET"
|
|
usage
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Backend status
|
|
status_backend() {
|
|
echo "[Backend Service]"
|
|
|
|
if [ ! -f "$BACKEND_PID_FILE" ]; then
|
|
echo " Status: NOT RUNNING"
|
|
return 0
|
|
fi
|
|
|
|
PID=$(cat "$BACKEND_PID_FILE")
|
|
if ps -p $PID > /dev/null 2>&1; then
|
|
echo " Status: RUNNING"
|
|
echo " PID: $PID"
|
|
echo " URL: http://localhost:8000/docs"
|
|
echo " Log: $BACKEND_LOG_FILE"
|
|
echo " Port: $(lsof -i :8000 2>/dev/null | grep LISTEN || echo 'N/A')"
|
|
else
|
|
echo " Status: NOT RUNNING"
|
|
rm -f "$BACKEND_PID_FILE"
|
|
fi
|
|
}
|
|
|
|
# Frontend status
|
|
status_frontend() {
|
|
echo "[Frontend Service]"
|
|
|
|
if [ ! -f "$FRONTEND_PID_FILE" ]; then
|
|
echo " Status: NOT RUNNING"
|
|
return 0
|
|
fi
|
|
|
|
PID=$(cat "$FRONTEND_PID_FILE")
|
|
if ps -p $PID > /dev/null 2>&1; then
|
|
echo " Status: RUNNING"
|
|
echo " PID: $PID"
|
|
echo " URL: http://localhost:3000"
|
|
echo " Log: $FRONTEND_LOG_FILE"
|
|
echo " Port: $(lsof -i :3000 2>/dev/null | grep LISTEN || echo 'N/A')"
|
|
else
|
|
echo " Status: NOT RUNNING"
|
|
rm -f "$FRONTEND_PID_FILE"
|
|
fi
|
|
}
|
|
|
|
# ============================================
|
|
# BUILD COMMAND
|
|
# ============================================
|
|
build_command() {
|
|
echo "========================================"
|
|
echo "CheckIn App V2 - Building Frontend"
|
|
echo "========================================"
|
|
echo ""
|
|
|
|
# Check Node.js
|
|
if ! command -v node &> /dev/null; then
|
|
log_error "Node.js not found"
|
|
log_info "Please install Node.js from https://nodejs.org/"
|
|
exit 1
|
|
fi
|
|
|
|
# Check frontend directory
|
|
if [ ! -d "frontend" ]; then
|
|
log_error "Frontend directory not found"
|
|
exit 1
|
|
fi
|
|
|
|
# Check node_modules
|
|
if [ ! -d "frontend/node_modules" ]; then
|
|
log_info "Installing frontend dependencies first..."
|
|
cd frontend
|
|
npm install
|
|
if [ $? -ne 0 ]; then
|
|
log_error "Failed to install dependencies"
|
|
exit 1
|
|
fi
|
|
cd ..
|
|
echo ""
|
|
fi
|
|
|
|
log_info "Building frontend for production..."
|
|
echo ""
|
|
|
|
# Build frontend
|
|
cd frontend
|
|
npm run build
|
|
BUILD_EXIT_CODE=$?
|
|
cd ..
|
|
|
|
if [ $BUILD_EXIT_CODE -eq 0 ]; then
|
|
echo ""
|
|
log_ok "Frontend built successfully!"
|
|
|
|
# Check if dist directory exists
|
|
if [ -d "frontend/dist" ]; then
|
|
DIST_SIZE=$(du -sh frontend/dist | cut -f1)
|
|
echo ""
|
|
echo "Build output:"
|
|
echo " Location: $APP_DIR/frontend/dist"
|
|
echo " Size: $DIST_SIZE"
|
|
echo ""
|
|
echo "File structure:"
|
|
ls -lh frontend/dist/
|
|
echo ""
|
|
log_info "You can now deploy the 'frontend/dist' directory to your web server"
|
|
else
|
|
log_warn "Build succeeded but dist directory not found"
|
|
fi
|
|
else
|
|
echo ""
|
|
log_error "Frontend build failed"
|
|
log_info "Check the output above for error details"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# ============================================
|
|
# LOG COMMAND
|
|
# ============================================
|
|
log_command() {
|
|
case $TARGET in
|
|
backend)
|
|
echo "========================================"
|
|
echo "Backend Real-time Logs (Press Ctrl+C to exit)"
|
|
echo "========================================"
|
|
echo ""
|
|
|
|
if [ ! -f "$BACKEND_LOG_FILE" ]; then
|
|
log_error "Log file does not exist: $BACKEND_LOG_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
tail -f "$BACKEND_LOG_FILE"
|
|
;;
|
|
frontend)
|
|
echo "========================================"
|
|
echo "Frontend Real-time Logs (Press Ctrl+C to exit)"
|
|
echo "========================================"
|
|
echo ""
|
|
|
|
if [ ! -f "$FRONTEND_LOG_FILE" ]; then
|
|
log_error "Log file does not exist: $FRONTEND_LOG_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
tail -f "$FRONTEND_LOG_FILE"
|
|
;;
|
|
all)
|
|
log_error "Cannot tail multiple logs simultaneously"
|
|
log_info "Use: ./manage.sh log backend OR ./manage.sh log frontend"
|
|
usage
|
|
;;
|
|
*)
|
|
log_error "Invalid target: $TARGET"
|
|
usage
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# ============================================
|
|
# USAGE
|
|
# ============================================
|
|
usage() {
|
|
echo "CheckIn App V2 - Unified Process Manager"
|
|
echo ""
|
|
echo "Usage: $0 COMMAND [TARGET]"
|
|
echo ""
|
|
echo "Commands:"
|
|
echo " start [TARGET] - Start service(s)"
|
|
echo " stop [TARGET] - Stop service(s)"
|
|
echo " restart [TARGET] - Restart service(s)"
|
|
echo " status [TARGET] - View service(s) status"
|
|
echo " log TARGET - View real-time logs (backend or frontend only)"
|
|
echo " build - Build frontend for production"
|
|
echo ""
|
|
echo "Targets:"
|
|
echo " backend - Backend API service (default port: 8000)"
|
|
echo " frontend - Frontend dev server (default port: 3000)"
|
|
echo " all - Both services (default)"
|
|
echo ""
|
|
echo "Examples:"
|
|
echo " $0 start # Start both services"
|
|
echo " $0 start backend # Start backend only"
|
|
echo " $0 stop all # Stop all services"
|
|
echo " $0 status # View all services status"
|
|
echo " $0 log backend # View backend logs"
|
|
echo " $0 build # Build frontend static files"
|
|
echo " $0 restart frontend # Restart frontend"
|
|
exit 1
|
|
}
|
|
|
|
# ============================================
|
|
# MAIN
|
|
# ============================================
|
|
if [ -z "$COMMAND" ]; then
|
|
usage
|
|
fi
|
|
|
|
case $COMMAND in
|
|
start)
|
|
start_command
|
|
;;
|
|
stop)
|
|
stop_command
|
|
;;
|
|
restart)
|
|
restart_command
|
|
;;
|
|
status)
|
|
status_command
|
|
;;
|
|
log)
|
|
log_command
|
|
;;
|
|
build)
|
|
build_command
|
|
;;
|
|
*)
|
|
usage
|
|
;;
|
|
esac
|
|
|
|
exit 0
|