Files
OCR/start.sh
egg 86a6633000 feat: consolidate env config and add deployment files
- Add debug_font_path, demo_docs_dir, e2e_api_base_url to config.py
- Fix hardcoded paths in pp_structure_debug.py, create_demo_images.py
- Fix hardcoded paths in test files
- Update .env.example with new configuration options
- Update .gitignore to exclude AI development files (.claude/, openspec/, AGENTS.md, CLAUDE.md)
- Add production startup script (start-prod.sh)
- Add README.md with project documentation
- Add 1panel Docker deployment files (docker-compose.yml, Dockerfiles, nginx.conf)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 15:02:16 +08:00

351 lines
9.6 KiB
Bash
Executable File

#!/bin/bash
# Tool_OCR - Unified Development Server Startup Script
# Usage:
# ./start.sh Start all services (backend + frontend)
# ./start.sh backend Start only backend
# ./start.sh frontend Start only frontend
# ./start.sh --stop Stop all services
# ./start.sh --status Show service status
# ./start.sh --help Show help
# Note: We don't use 'set -e' here because stop commands may fail gracefully
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
BLUE='\033[0;34m'
NC='\033[0m'
# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PID_DIR="$SCRIPT_DIR/.pid"
BACKEND_PID_FILE="$PID_DIR/backend.pid"
FRONTEND_PID_FILE="$PID_DIR/frontend.pid"
BACKEND_HOST=${BACKEND_HOST:-0.0.0.0}
BACKEND_PORT=${BACKEND_PORT:-8000}
FRONTEND_HOST=${FRONTEND_HOST:-0.0.0.0}
FRONTEND_PORT=${FRONTEND_PORT:-5173}
# Create PID directory
mkdir -p "$PID_DIR"
# Functions
print_header() {
echo ""
echo -e "${BLUE}================================${NC}"
echo -e "${BLUE} Tool_OCR Development Server${NC}"
echo -e "${BLUE}================================${NC}"
echo ""
}
show_help() {
echo "Tool_OCR - Development Server Manager"
echo ""
echo "Usage: ./start.sh [command]"
echo ""
echo "Commands:"
echo " (none) Start all services (backend + frontend)"
echo " backend Start only backend service"
echo " frontend Start only frontend service"
echo " --stop Stop all running services"
echo " --status Show status of services"
echo " --help Show this help message"
echo ""
echo "Examples:"
echo " ./start.sh # Start everything"
echo " ./start.sh backend # Start only backend"
echo " ./start.sh --stop # Stop all services"
echo ""
}
check_requirements() {
local missing=0
# Check virtual environment
if [ ! -d "$SCRIPT_DIR/venv" ]; then
echo -e "${RED}Error: Python virtual environment not found${NC}"
echo "Please run: ./setup_dev_env.sh"
missing=1
fi
# Check node_modules
if [ ! -d "$SCRIPT_DIR/frontend/node_modules" ]; then
echo -e "${RED}Error: Frontend dependencies not found${NC}"
echo "Please run: ./setup_dev_env.sh"
missing=1
fi
# Check .env.local
if [ ! -f "$SCRIPT_DIR/.env.local" ]; then
echo -e "${RED}Error: .env.local not found${NC}"
echo "Please copy .env.example to .env.local and configure"
missing=1
fi
return $missing
}
load_env() {
# Load environment variables from root .env.local (if present).
# This keeps backend/frontend config in sync without hardcoding ports/URLs in scripts.
if [ -f "$SCRIPT_DIR/.env.local" ]; then
set -a
# shellcheck disable=SC1090
source "$SCRIPT_DIR/.env.local"
set +a
fi
}
is_running() {
local pid_file=$1
if [ -f "$pid_file" ]; then
local pid=$(cat "$pid_file")
if ps -p "$pid" > /dev/null 2>&1; then
return 0
else
# PID file exists but process is not running, clean up
rm -f "$pid_file"
fi
fi
return 1
}
get_pid() {
local pid_file=$1
if [ -f "$pid_file" ]; then
cat "$pid_file"
fi
}
start_backend() {
if is_running "$BACKEND_PID_FILE"; then
echo -e "${YELLOW}Backend already running (PID: $(get_pid $BACKEND_PID_FILE))${NC}"
return 0
fi
echo -e "${GREEN}Starting backend server...${NC}"
# Activate virtual environment
source "$SCRIPT_DIR/venv/bin/activate"
# Load environment variables
load_env
# Start backend in background
cd "$SCRIPT_DIR/backend"
# Create necessary directories
mkdir -p uploads/{temp,processed,images}
mkdir -p storage/{markdown,json,exports,results}
mkdir -p models/paddleocr
mkdir -p logs
# Start uvicorn
nohup uvicorn app.main:app --reload --host "$BACKEND_HOST" --port "$BACKEND_PORT" > "$SCRIPT_DIR/.pid/backend.log" 2>&1 &
local pid=$!
echo $pid > "$BACKEND_PID_FILE"
cd "$SCRIPT_DIR"
# Wait a moment and verify
sleep 2
if is_running "$BACKEND_PID_FILE"; then
echo -e "${GREEN}Backend started (PID: $pid)${NC}"
echo -e " API Docs: http://localhost:$BACKEND_PORT/docs"
echo -e " Health: http://localhost:$BACKEND_PORT/health"
else
echo -e "${RED}Backend failed to start. Check .pid/backend.log${NC}"
return 1
fi
}
start_frontend() {
if is_running "$FRONTEND_PID_FILE"; then
echo -e "${YELLOW}Frontend already running (PID: $(get_pid $FRONTEND_PID_FILE))${NC}"
return 0
fi
echo -e "${GREEN}Starting frontend server...${NC}"
# Load environment variables so Vite config can use FRONTEND_PORT/FRONTEND_HOST/etc.
load_env
# Load nvm
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
cd "$SCRIPT_DIR/frontend"
# Start vite in background
nohup npm run dev > "$SCRIPT_DIR/.pid/frontend.log" 2>&1 &
local pid=$!
echo $pid > "$FRONTEND_PID_FILE"
cd "$SCRIPT_DIR"
# Wait a moment and verify
sleep 3
if is_running "$FRONTEND_PID_FILE"; then
echo -e "${GREEN}Frontend started (PID: $pid)${NC}"
echo -e " URL: http://localhost:$FRONTEND_PORT"
else
echo -e "${RED}Frontend failed to start. Check .pid/frontend.log${NC}"
return 1
fi
}
kill_process_tree() {
local pid=$1
# Kill all child processes first
pkill -TERM -P "$pid" 2>/dev/null || true
# Then kill the parent
kill -TERM "$pid" 2>/dev/null || true
}
force_kill_process_tree() {
local pid=$1
# Force kill all child processes
pkill -9 -P "$pid" 2>/dev/null || true
# Force kill the parent
kill -9 "$pid" 2>/dev/null || true
}
kill_by_port() {
local port=$1
local pids=$(lsof -ti :$port 2>/dev/null)
if [ -n "$pids" ]; then
echo "$pids" | xargs kill -TERM 2>/dev/null || true
sleep 1
# Force kill if still running
pids=$(lsof -ti :$port 2>/dev/null)
if [ -n "$pids" ]; then
echo "$pids" | xargs kill -9 2>/dev/null || true
fi
fi
}
stop_service() {
local name=$1
local pid_file=$2
local port=$3
if is_running "$pid_file"; then
local pid=$(get_pid "$pid_file")
echo -e "${YELLOW}Stopping $name (PID: $pid)...${NC}"
# Kill the entire process tree
kill_process_tree "$pid"
# Wait up to 5 seconds
local count=0
while [ $count -lt 5 ] && is_running "$pid_file"; do
sleep 1
count=$((count + 1))
done
# Force kill if still running
if is_running "$pid_file"; then
force_kill_process_tree "$pid"
fi
rm -f "$pid_file"
fi
# Also kill any orphaned processes by port (fallback)
if [ -n "$port" ]; then
local port_pids=$(lsof -ti :$port 2>/dev/null)
if [ -n "$port_pids" ]; then
echo -e "${YELLOW}Cleaning up orphaned processes on port $port...${NC}"
kill_by_port "$port"
fi
fi
echo -e "${GREEN}$name stopped${NC}"
}
stop_all() {
echo -e "${YELLOW}Stopping all services...${NC}"
stop_service "Backend" "$BACKEND_PID_FILE" "$BACKEND_PORT"
stop_service "Frontend" "$FRONTEND_PID_FILE" "$FRONTEND_PORT"
echo -e "${GREEN}All services stopped${NC}"
}
show_status() {
echo -e "${BLUE}Service Status:${NC}"
echo ""
if is_running "$BACKEND_PID_FILE"; then
local pid=$(get_pid "$BACKEND_PID_FILE")
echo -e " Backend: ${GREEN}Running${NC} (PID: $pid)"
echo -e " http://localhost:$BACKEND_PORT"
else
echo -e " Backend: ${RED}Stopped${NC}"
fi
if is_running "$FRONTEND_PID_FILE"; then
local pid=$(get_pid "$FRONTEND_PID_FILE")
echo -e " Frontend: ${GREEN}Running${NC} (PID: $pid)"
echo -e " http://localhost:$FRONTEND_PORT"
else
echo -e " Frontend: ${RED}Stopped${NC}"
fi
echo ""
}
# Main
case "${1:-all}" in
--help|-h)
show_help
;;
--stop)
stop_all
;;
--status)
show_status
;;
backend)
print_header
check_requirements || exit 1
start_backend
echo ""
echo -e "${YELLOW}Press Ctrl+C to stop (or use ./start.sh --stop)${NC}"
echo -e "${YELLOW}Logs: tail -f .pid/backend.log${NC}"
;;
frontend)
print_header
check_requirements || exit 1
start_frontend
echo ""
echo -e "${YELLOW}Press Ctrl+C to stop (or use ./start.sh --stop)${NC}"
echo -e "${YELLOW}Logs: tail -f .pid/frontend.log${NC}"
;;
all|"")
print_header
check_requirements || exit 1
start_backend
start_frontend
echo ""
echo -e "${GREEN}================================${NC}"
echo -e "${GREEN}All services started!${NC}"
echo -e "${GREEN}================================${NC}"
echo ""
echo "Access the application:"
echo -e " Frontend: ${BLUE}http://localhost:$FRONTEND_PORT${NC}"
echo -e " API Docs: ${BLUE}http://localhost:$BACKEND_PORT/docs${NC}"
echo ""
echo -e "${YELLOW}Use ./start.sh --stop to stop all services${NC}"
echo -e "${YELLOW}Use ./start.sh --status to check status${NC}"
echo ""
echo "Logs:"
echo " Backend: tail -f .pid/backend.log"
echo " Frontend: tail -f .pid/frontend.log"
;;
*)
echo -e "${RED}Unknown command: $1${NC}"
show_help
exit 1
;;
esac