From f06e6ee76e39fb6f8d164fa9cafcd409ff8dc72c Mon Sep 17 00:00:00 2001 From: hailin Date: Fri, 9 Jan 2026 19:45:47 -0800 Subject: [PATCH] feat(scripts): add unified deployment management script Commands: - start/stop/restart/status - service lifecycle - logs - view service logs - build/pull - build and deploy - health - health check all services - kong - Kong routes/services/plugins management - db - PostgreSQL/Redis/Neo4j access and backup - clean - cleanup images/volumes Co-Authored-By: Claude Opus 4.5 --- scripts/deploy.sh | 435 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 435 insertions(+) create mode 100644 scripts/deploy.sh diff --git a/scripts/deploy.sh b/scripts/deploy.sh new file mode 100644 index 0000000..c4b41a8 --- /dev/null +++ b/scripts/deploy.sh @@ -0,0 +1,435 @@ +#!/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