Files
pixel/start.sh
张鹏 f9f4560459 Initial commit: Pixel AI comic/video creation platform
- FastAPI backend with SQLModel, Alembic migrations, AgentScope agents
- Next.js 15 frontend with React 19, Tailwind, Zustand, React Flow
- Multi-provider AI system (DashScope, Kling, MiniMax, Volcengine, OpenAI, etc.)
- All HTTP clients migrated from sync requests to async httpx
- Admin-managed API keys via environment variables
- SSRF vulnerability fixed in ensure_url()
2026-04-29 01:20:12 +08:00

344 lines
9.0 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Configuration
BACKEND_PORT=8000
FRONTEND_PORT=3000
BACKEND_DIR="backend"
FRONTEND_DIR="frontend"
LOG_DIR="logs"
# Create logs directory if it doesn't exist
mkdir -p "$LOG_DIR"
# Log files
BACKEND_LOG="$LOG_DIR/backend.log"
FRONTEND_LOG="$LOG_DIR/frontend.log"
# Function to print colored messages
print_info() {
echo -e "${BLUE}${NC} $1"
}
print_success() {
echo -e "${GREEN}${NC} $1"
}
print_warning() {
echo -e "${YELLOW}${NC} $1"
}
print_error() {
echo -e "${RED}${NC} $1"
}
# Function to kill background processes on exit
cleanup() {
echo ""
print_info "Stopping all services..."
# Kill all background jobs
jobs -p | xargs -r kill 2>/dev/null
# Wait a moment for graceful shutdown
sleep 1
# Force kill if still running
jobs -p | xargs -r kill -9 2>/dev/null
print_success "All services stopped"
exit 0
}
# Function to check if command exists
command_exists() {
command -v "$1" >/dev/null 2>&1
}
# Function to check prerequisites
check_prerequisites() {
print_info "Checking prerequisites..."
local missing_deps=()
# Check for required commands
if ! command_exists "uv"; then
missing_deps+=("uv (Python package manager)")
fi
if ! command_exists "node"; then
missing_deps+=("node (Node.js)")
fi
if ! command_exists "pnpm"; then
missing_deps+=("pnpm (Node package manager)")
fi
if ! command_exists "curl"; then
missing_deps+=("curl")
fi
if ! command_exists "lsof"; then
print_warning "lsof not found, port checking will be limited"
fi
if [ ${#missing_deps[@]} -gt 0 ]; then
print_error "Missing required dependencies:"
for dep in "${missing_deps[@]}"; do
echo " - $dep"
done
echo ""
echo "Please install missing dependencies and try again."
exit 1
fi
print_success "All prerequisites satisfied"
}
# Function to check and free port
check_and_free_port() {
local port=$1
local name=$2
if ! command_exists "lsof"; then
return 0
fi
# Check if port is in use
if lsof -i :$port >/dev/null 2>&1; then
print_warning "Port $port ($name) is in use"
# Get PIDs using the port
local pids=$(lsof -ti :$port)
# Ask user for confirmation
read -p "Kill processes on port $port? (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
for pid in $pids; do
print_info "Killing process $pid on port $port..."
kill -9 $pid 2>/dev/null
done
sleep 1
# Verify if port is still in use
if lsof -i :$port >/dev/null 2>&1; then
print_error "Failed to free port $port. Please free it manually."
exit 1
else
print_success "Port $port freed successfully"
fi
else
print_error "Cannot start service on port $port. Exiting."
exit 1
fi
fi
}
# Function to check if directory exists
check_directory() {
local dir=$1
local name=$2
if [ ! -d "$dir" ]; then
print_error "$name directory not found: $dir"
exit 1
fi
}
# Function to start backend
start_backend() {
print_info "Starting Backend on port $BACKEND_PORT..."
cd "$BACKEND_DIR" || exit 1
# Check if .env file exists
if [ ! -f ".env" ]; then
print_warning "Backend .env file not found. Using default configuration."
fi
# Set PYTHONPATH
export PYTHONPATH=$PYTHONPATH:$(pwd)
# Start backend with logging
uv run uvicorn src.main:app --reload --port $BACKEND_PORT > "../$BACKEND_LOG" 2>&1 &
BACKEND_PID=$!
cd ..
print_info "Backend PID: $BACKEND_PID (logs: $BACKEND_LOG)"
}
# Function to wait for backend to be ready
wait_for_backend() {
print_info "Waiting for backend to be ready..."
local max_retries=30
local retry_count=0
local health_url="http://localhost:$BACKEND_PORT/health"
while [ $retry_count -lt $max_retries ]; do
if curl -s "$health_url" > /dev/null 2>&1; then
print_success "Backend is ready!"
return 0
fi
# Check if backend process is still running
if ! kill -0 $BACKEND_PID 2>/dev/null; then
print_error "Backend process died. Check logs: $BACKEND_LOG"
tail -n 20 "$BACKEND_LOG"
return 1
fi
retry_count=$((retry_count + 1))
# Show progress
printf "\r Attempt %d/%d..." $retry_count $max_retries
sleep 1
done
echo ""
print_error "Backend failed to start after $max_retries seconds"
print_info "Last 20 lines of backend log:"
tail -n 20 "$BACKEND_LOG"
return 1
}
# Function to start frontend
start_frontend() {
print_info "Starting Frontend on port $FRONTEND_PORT..."
cd "$FRONTEND_DIR" || exit 1
# Check if node_modules exists
if [ ! -d "node_modules" ]; then
print_warning "node_modules not found. Running pnpm install..."
pnpm install
fi
# Start frontend with logging
pnpm dev > "../$FRONTEND_LOG" 2>&1 &
FRONTEND_PID=$!
cd ..
print_info "Frontend PID: $FRONTEND_PID (logs: $FRONTEND_LOG)"
}
# Function to wait for frontend to be ready
wait_for_frontend() {
print_info "Waiting for frontend to be ready..."
local max_retries=30
local retry_count=0
while [ $retry_count -lt $max_retries ]; do
if curl -s "http://localhost:$FRONTEND_PORT" > /dev/null 2>&1; then
print_success "Frontend is ready!"
return 0
fi
# Check if frontend process is still running
if ! kill -0 $FRONTEND_PID 2>/dev/null; then
print_error "Frontend process died. Check logs: $FRONTEND_LOG"
tail -n 20 "$FRONTEND_LOG"
return 1
fi
retry_count=$((retry_count + 1))
# Show progress
printf "\r Attempt %d/%d..." $retry_count $max_retries
sleep 1
done
echo ""
print_error "Frontend failed to start after $max_retries seconds"
print_info "Last 20 lines of frontend log:"
tail -n 20 "$FRONTEND_LOG"
return 1
}
# Function to display service information
display_info() {
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
print_success "All services started successfully!"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo " 📡 Backend API: http://localhost:$BACKEND_PORT"
echo " 📚 API Docs: http://localhost:$BACKEND_PORT/docs"
echo " 📖 ReDoc: http://localhost:$BACKEND_PORT/redoc"
echo " 🏥 Health Check: http://localhost:$BACKEND_PORT/health"
echo " 📊 Metrics: http://localhost:$BACKEND_PORT/metrics"
echo ""
echo " 🎨 Frontend: http://localhost:$FRONTEND_PORT"
echo ""
echo " 📝 Backend Logs: $BACKEND_LOG"
echo " 📝 Frontend Logs: $FRONTEND_LOG"
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
print_info "Press Ctrl+C to stop all services"
echo ""
}
# Main execution
main() {
echo ""
echo "╔═══════════════════════════════════════════════════════╗"
echo "║ Pixel Development Environment Startup ║"
echo "╚═══════════════════════════════════════════════════════╝"
echo ""
# Trap SIGINT (Ctrl+C) and call cleanup
trap cleanup SIGINT SIGTERM
# Check prerequisites
check_prerequisites
# Check directories
check_directory "$BACKEND_DIR" "Backend"
check_directory "$FRONTEND_DIR" "Frontend"
# Check and free ports
check_and_free_port $BACKEND_PORT "Backend"
check_and_free_port $FRONTEND_PORT "Frontend"
# Start backend
start_backend
# Wait for backend to be ready
if ! wait_for_backend; then
cleanup
exit 1
fi
# Start frontend
start_frontend
# Wait for frontend to be ready
if ! wait_for_frontend; then
cleanup
exit 1
fi
# Display service information
display_info
# Wait for processes
wait
}
# Run main function
main