#!/bin/bash #=============================================================================== # iConsulting 部署管理脚本 # # 用法: # ./scripts/deploy.sh [options] # # 命令: # start 启动所有服务 # stop 停止所有服务 # restart 重启所有服务 # status 查看服务状态 # logs 查看日志 # build 构建服务镜像 # pull 拉取最新代码并重新部署 # health 健康检查 # kong Kong 相关操作 # db 数据库相关操作 # clean 清理资源 # #=============================================================================== set -e # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # 项目根目录 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" cd "$PROJECT_ROOT" #=============================================================================== # 辅助函数 #=============================================================================== log_info() { echo -e "${BLUE}[INFO]${NC} $1" } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } print_header() { echo "" echo "==============================================" echo " $1" echo "==============================================" echo "" } #=============================================================================== # 服务管理 #=============================================================================== cmd_start() { print_header "启动所有服务" log_info "启动基础设施..." docker compose up -d postgres redis neo4j log_info "等待数据库就绪..." sleep 10 log_info "启动 Kong API 网关..." docker compose up -d kong log_info "等待 Kong 就绪..." sleep 5 log_info "启动后端服务..." docker compose up -d user-service payment-service knowledge-service conversation-service evolution-service log_info "启动 Nginx..." docker compose up -d nginx log_success "所有服务已启动" cmd_status } cmd_stop() { print_header "停止所有服务" docker compose down log_success "所有服务已停止" } cmd_restart() { local service=$1 if [ -n "$service" ]; then print_header "重启服务: $service" docker compose restart "$service" log_success "$service 已重启" else print_header "重启所有服务" docker compose restart log_success "所有服务已重启" fi } cmd_status() { print_header "服务状态" docker compose ps } cmd_logs() { local service=$1 local lines=${2:-100} if [ -n "$service" ]; then docker compose logs -f --tail="$lines" "$service" else docker compose logs -f --tail="$lines" fi } #=============================================================================== # 构建和部署 #=============================================================================== cmd_build() { local service=$1 if [ -n "$service" ]; then print_header "构建服务: $service" docker compose build --no-cache "$service" else print_header "构建所有服务" docker compose build --no-cache fi log_success "构建完成" } cmd_pull() { print_header "拉取最新代码并部署" log_info "拉取最新代码..." git pull log_info "重新构建服务..." docker compose build log_info "重新启动服务..." docker compose up -d log_success "部署完成" cmd_status } #=============================================================================== # 健康检查 #=============================================================================== cmd_health() { print_header "健康检查" echo "服务健康状态:" echo "" # 检查各服务 services=( "postgres:5432:PostgreSQL" "redis:6379:Redis" "neo4j:7474:Neo4j" "kong:8001:Kong" "user-service:3001:User Service" "payment-service:3002:Payment Service" "knowledge-service:3003:Knowledge Service" "conversation-service:3004:Conversation Service" "evolution-service:3005:Evolution Service" "nginx:80:Nginx" ) for service_info in "${services[@]}"; do IFS=':' read -r service port name <<< "$service_info" if docker compose exec -T "$service" wget -q --spider "http://localhost:$port/health" 2>/dev/null || \ docker compose exec -T "$service" curl -sf "http://localhost:$port/health" 2>/dev/null || \ docker compose exec -T "$service" pg_isready 2>/dev/null || \ docker compose exec -T "$service" redis-cli ping 2>/dev/null | grep -q PONG; then echo -e " ${GREEN}✓${NC} $name" else # 检查容器是否运行 if docker compose ps "$service" 2>/dev/null | grep -q "Up"; then echo -e " ${YELLOW}?${NC} $name (运行中,但健康检查失败)" else echo -e " ${RED}✗${NC} $name (未运行)" fi fi done echo "" # Kong 路由检查 log_info "Kong 路由配置:" curl -s http://localhost:8001/routes 2>/dev/null | grep -o '"name":"[^"]*"' | sed 's/"name":"//g; s/"//g' | while read name; do echo " - $name" done || echo " (无法获取)" echo "" } #=============================================================================== # Kong 管理 #=============================================================================== cmd_kong() { local subcmd=$1 shift case "$subcmd" in status) print_header "Kong 状态" curl -s http://localhost:8001/status | jq . 2>/dev/null || echo "Kong 未响应" ;; routes) print_header "Kong 路由" curl -s http://localhost:8001/routes | jq '.data[] | {name, paths, methods}' 2>/dev/null || echo "Kong 未响应" ;; services) print_header "Kong 服务" curl -s http://localhost:8001/services | jq '.data[] | {name, host, port}' 2>/dev/null || echo "Kong 未响应" ;; plugins) print_header "Kong 插件" curl -s http://localhost:8001/plugins | jq '.data[] | {name, enabled}' 2>/dev/null || echo "Kong 未响应" ;; reload) print_header "重载 Kong 配置" docker compose restart kong log_success "Kong 已重载" ;; test) print_header "测试 Kong API 路由" echo "测试 /api/v1/conversations:" curl -s -o /dev/null -w " HTTP %{http_code}\n" -X POST http://localhost:8000/api/v1/conversations \ -H "Content-Type: application/json" \ -H "x-user-id: test" \ -d '{}' echo "测试 /api/v1/users:" curl -s -o /dev/null -w " HTTP %{http_code}\n" http://localhost:8000/api/v1/users/health 2>/dev/null || echo " (无 health 端点)" ;; *) echo "Kong 子命令:" echo " status - 查看 Kong 状态" echo " routes - 查看路由配置" echo " services - 查看服务配置" echo " plugins - 查看插件配置" echo " reload - 重载配置" echo " test - 测试 API 路由" ;; esac } #=============================================================================== # 数据库管理 #=============================================================================== cmd_db() { local subcmd=$1 shift case "$subcmd" in psql) print_header "连接 PostgreSQL" docker compose exec postgres psql -U postgres -d iconsulting ;; redis) print_header "连接 Redis" docker compose exec redis redis-cli -a redis123 ;; neo4j) print_header "Neo4j 浏览器" echo "访问: http://localhost:7474" echo "用户: neo4j" echo "密码: neo4j123" ;; backup) local backup_dir="backups/$(date +%Y%m%d_%H%M%S)" mkdir -p "$backup_dir" print_header "备份数据库" log_info "备份 PostgreSQL..." docker compose exec -T postgres pg_dump -U postgres iconsulting > "$backup_dir/postgres.sql" log_info "备份 Redis..." docker compose exec -T redis redis-cli -a redis123 BGSAVE log_success "备份完成: $backup_dir" ;; *) echo "数据库子命令:" echo " psql - 连接 PostgreSQL" echo " redis - 连接 Redis" echo " neo4j - Neo4j 连接信息" echo " backup - 备份数据库" ;; esac } #=============================================================================== # 清理 #=============================================================================== cmd_clean() { local subcmd=$1 case "$subcmd" in images) print_header "清理未使用的镜像" docker image prune -f ;; volumes) print_header "清理未使用的卷" log_warn "这将删除未使用的数据卷!" read -p "确定要继续吗?(y/N) " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then docker volume prune -f fi ;; all) print_header "完全清理" log_warn "这将停止所有容器并删除所有数据!" read -p "确定要继续吗?(y/N) " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then docker compose down -v --rmi all log_success "清理完成" fi ;; *) echo "清理子命令:" echo " images - 清理未使用的镜像" echo " volumes - 清理未使用的卷" echo " all - 完全清理(危险)" ;; esac } #=============================================================================== # 主入口 #=============================================================================== show_help() { echo "iConsulting 部署管理脚本" echo "" echo "用法: $0 [options]" echo "" echo "命令:" echo " start 启动所有服务" echo " stop 停止所有服务" echo " restart [service] 重启服务(可指定单个服务)" echo " status 查看服务状态" echo " logs [service] 查看日志" echo " build [service] 构建服务镜像" echo " pull 拉取最新代码并部署" echo " health 健康检查" echo " kong Kong 管理" echo " db 数据库管理" echo " clean 清理资源" echo "" echo "示例:" echo " $0 start # 启动所有服务" echo " $0 logs conversation-service # 查看对话服务日志" echo " $0 kong routes # 查看 Kong 路由" echo " $0 db psql # 连接 PostgreSQL" echo "" } # 主命令分发 case "$1" in start) cmd_start ;; stop) cmd_stop ;; restart) cmd_restart "$2" ;; status) cmd_status ;; logs) cmd_logs "$2" "$3" ;; build) cmd_build "$2" ;; pull) cmd_pull ;; health) cmd_health ;; kong) shift cmd_kong "$@" ;; db) shift cmd_db "$@" ;; clean) shift cmd_clean "$@" ;; help|--help|-h) show_help ;; *) if [ -n "$1" ]; then log_error "未知命令: $1" fi show_help exit 1 ;; esac