1. 概述
本脚本 (start.sh) 是一个自动化的环境启动工具,专为 AI Shop 项目设计。它旨在简化开发环境的搭建过程,通过一条命令即可完成数据库、缓存、后端服务及前端服务的启动与状态检查,并自动在浏览器中打开预览页面。
该脚本适用于 macOS 和 Linux 环境(依赖 bash, docker, python3, npm 等工具)。
2. 核心功能
脚本按顺序执行以下关键步骤:
- 环境定位 :自动获取脚本所在目录作为项目根目录 (
PROJECT_ROOT)。 - Docker 服务管理 :
- 检测 Docker 是否运行,若未运行则尝试自动启动 Docker Desktop (macOS)。
- 使用
docker compose启动基础设施容器(数据库 PostgreSQL 和 缓存 Redis)。 - 智能等待:轮询检测端口,确保数据库 (5432) 和 Redis (6379) 完全就绪后才继续。
- 后端服务启动 :
- 进入
e-commerce目录。 - 校验
requirements.txt是否存在。 - 使用
uvicorn启动 Python 后端服务(端口 8000),并在后台运行。 - 智能等待:确保后端 API 可访问后才继续。
- 进入
- 前端服务启动 :
- 进入
frontend目录。 - 自动检测
node_modules,若不存在则执行npm install。 - 使用
vite启动前端开发服务器(端口 5173),并在后台运行。 - 智能等待:确保前端页面可访问后才继续。
- 进入
- 收尾工作 :
- 自动在默认浏览器中打开前端预览页面 (
http://localhost:5173)。 - 将后端和前端的进程 ID (PID) 保存至
services.pid文件,便于后续管理或停止服务。
- 自动在默认浏览器中打开前端预览页面 (
3. 技术细节与逻辑
3.1 端口检测机制
脚本定义了 check_port 函数,利用 lsof 命令检测指定端口是否有进程监听。这是实现"服务就绪等待"逻辑的基础。
3.2 服务就绪等待 (wait_for_service)
为了避免服务启动顺序依赖导致的错误(例如后端在数据库未准备好时启动失败),脚本实现了重试机制:
- 最大尝试次数:30 次。
- 间隔时间:每次尝试间隔 2 秒。
- 超时处理:若超过最大尝试次数仍未检测到端口监听,脚本将报错并终止相应流程。
3.3 进程守护
后端和前端服务均使用 nohup ... & 方式在后台运行,并将标准输出和错误重定向到各自的日志文件中:
- 后端日志:
e-commerce/backend.log - 前端日志:
frontend/frontend.log
4. 目录结构要求
为了让脚本正常运行,项目目录结构应如下所示:
PROJECT_ROOT/
├── start.sh # 本启动脚本
├── docker-compose.yml # Docker 编排文件
├── services.pid # (运行后生成) 存储进程ID
├── e-commerce/ # 后端目录
│ ├── requirements.txt
│ └── app/
│ └── main.py
└── frontend/ # 前端目录
├── package.json
└── node_modules/ # (可选,脚本会自动安装)
5. 使用方法
前置条件
请确保您的系统已安装以下工具:
- Docker & Docker Compose
- Python 3 (包含
uvicorn) - Node.js & npm
- Bash shell
启动步骤
-
赋予脚本执行权限(首次使用时):
chmod +x start.sh -
运行脚本:
./start.sh
预期输出
脚本运行成功后,终端将显示类似以下信息:
All services started successfully!
Backend: http://localhost:8000 (PID: 12345)
Frontend: http://localhost:5173 (PID: 67890)
Logs: backend.log and frontend.log in respective directories
同时,浏览器会自动跳转到前端页面。
code:
bash
#!/bin/bash
# Get the directory where the script is located
PROJECT_ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
echo "Starting AI Shop Environment..."
# Function to check if a port is in use
check_port() {
local port=$1
if lsof -Pi :$port -sTCP:LISTEN -t >/dev/null 2>&1; then
return 0
else
return 1
fi
}
# Function to wait for a service to be ready
wait_for_service() {
local port=$1
local service_name=$2
local max_attempts=30
local attempt=0
echo "Waiting for $service_name to be ready on port $port..."
while ! check_port $port; do
attempt=$((attempt + 1))
if [ $attempt -ge $max_attempts ]; then
echo "Timeout waiting for $service_name on port $port"
return 1
fi
sleep 2
echo -n "."
done
echo ""
echo "$service_name is ready!"
return 0
}
# 1. Start Docker Containers
echo "Checking Docker status..."
if ! docker info > /dev/null 2>&1; then
echo "Docker is not running. Please start Docker Desktop first."
open -a Docker
echo "Waiting for Docker to start..."
while ! docker info > /dev/null 2>&1; do
sleep 2
echo -n "."
done
echo ""
fi
echo "Starting database and redis..."
cd "$PROJECT_ROOT"
docker compose up -d
# Wait for database and redis to be ready
wait_for_service 5432 "PostgreSQL"
wait_for_service 6379 "Redis"
# 2. Start Backend
echo "Starting Backend..."
cd "$PROJECT_ROOT/e-commerce"
# Check if Python dependencies are installed
if [ ! -f "requirements.txt" ]; then
echo "Error: requirements.txt not found in e-commerce directory"
exit 1
fi
# Start backend in background
nohup python3 -m uvicorn app.main:app --reload --host 0.0.0.0 --port 8000 > backend.log 2>&1 &
BACKEND_PID=$!
echo "Backend started with PID: $BACKEND_PID"
# Wait for backend to be ready
wait_for_service 8000 "Backend"
# 3. Start Frontend
echo "Starting Frontend..."
cd "$PROJECT_ROOT/frontend"
# Check if node_modules exists
if [ ! -d "node_modules" ]; then
echo "Installing frontend dependencies..."
npm install
fi
# Start frontend in background
nohup ./node_modules/.bin/vite --host 0.0.0.0 --port 5173 > frontend.log 2>&1 &
FRONTEND_PID=$!
echo "Frontend started with PID: $FRONTEND_PID"
# Wait for frontend to be ready
wait_for_service 5173 "Frontend"
# 4. Open preview page
echo "Opening preview page..."
sleep 3 # Give services a moment to fully start
open "http://localhost:5173"
# Save PIDs for cleanup
echo "Backend PID: $BACKEND_PID" > "$PROJECT_ROOT/services.pid"
echo "Frontend PID: $FRONTEND_PID" >> "$PROJECT_ROOT/services.pid"
echo "All services started successfully!"
echo "Backend: http://localhost:8000 (PID: $BACKEND_PID)"
echo "Frontend: http://localhost:5173 (PID: $FRONTEND_PID)"
echo "Logs: backend.log and frontend.log in respective directories"