#!/usr/bin/env bash # ═══════════════════════════════════════════════════════════════════════════════ # 天工智能体平台 — 一键安装脚本 # 用法: bash install.sh # ═══════════════════════════════════════════════════════════════════════════════ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" cd "$SCRIPT_DIR" RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' CYAN='\033[0;36m' NC='\033[0m' banner() { echo "" echo -e "${CYAN}╔══════════════════════════════════════════════╗${NC}" echo -e "${CYAN}║ 天工智能体平台 — 一键安装向导 ║${NC}" echo -e "${CYAN}╚══════════════════════════════════════════════╝${NC}" echo "" } info() { echo -e "${GREEN}[✓]${NC} $*"; } warn() { echo -e "${YELLOW}[!]${NC} $*"; } error() { echo -e "${RED}[✗]${NC} $*"; exit 1; } # ─── 1. 前置检查 ───────────────────────────────────────────────────────────── banner echo "正在检查系统环境..." # Docker if ! command -v docker &>/dev/null; then error "未找到 Docker。请先安装 Docker: https://docs.docker.com/get-docker/" fi info "Docker 已安装: $(docker --version)" # Docker Compose (v2) if docker compose version &>/dev/null; then COMPOSE="docker compose" elif command -v docker-compose &>/dev/null; then COMPOSE="docker-compose" else error "未找到 Docker Compose。请安装 Docker Compose v2" fi info "Docker Compose 可用: $COMPOSE" # 磁盘空间 avail_gb=$(df -BG . | tail -1 | awk '{print $4}' | sed 's/G//') if [ "${avail_gb:-0}" -lt 5 ]; then warn "磁盘可用空间不足 5GB ($avail_gb GB),建议至少保留 10GB" else info "磁盘可用空间: ${avail_gb} GB" fi # ─── 2. 环境配置 ───────────────────────────────────────────────────────────── echo "" echo -e "${CYAN}── 配置环境变量 ──${NC}" echo "" ENV_FILE="./backend/.env" COMPOSE_FILE="./docker-compose.prod.yml" # 检查是否已有 .env if [ -f "$ENV_FILE" ]; then echo -e "${YELLOW}检测到已有 .env 文件: $ENV_FILE${NC}" read -r -p "是否覆盖配置?(y/N): " OVERWRITE if [[ ! "$OVERWRITE" =~ ^[Yy] ]]; then info "保留现有 .env 配置" else NEED_CONFIG=true fi else NEED_CONFIG=true fi if [ "${NEED_CONFIG:-false}" = true ]; then # 从模板复制 if [ -f "./backend/.env.example" ]; then cp "./backend/.env.example" "$ENV_FILE" info "已从 .env.example 创建 .env" else touch "$ENV_FILE" fi echo "" echo "请输入以下配置(直接回车使用默认值):" # MySQL 密码 read -r -p "MySQL root 密码 [change-me]: " MYSQL_PASS MYSQL_PASS=${MYSQL_PASS:-change-me} # JWT 密钥 read -r -p "JWT 密钥(留空自动生成): " JWT_KEY JWT_KEY=${JWT_KEY:-$(openssl rand -hex 32 2>/dev/null || echo "prod-jwt-$(date +%s)")} # 应用密钥 read -r -p "应用 SECRET_KEY(留空自动生成): " APP_KEY APP_KEY=${APP_KEY:-$(openssl rand -hex 32 2>/dev/null || echo "prod-secret-$(date +%s)")} # AI API Key read -r -p "DeepSeek API Key: " DS_KEY read -r -p "OpenAI API Key(可选): " OAI_KEY # 外部URL read -r -p "外部访问地址 [http://localhost]: " EXT_URL EXT_URL=${EXT_URL:-http://localhost} # 写入 .env cat > "$ENV_FILE" << EOF APP_NAME=天工智能体平台 APP_VERSION=1.0.0 DEBUG=False SECRET_KEY=${APP_KEY} DATABASE_URL=mysql+pymysql://root:${MYSQL_PASS}@mysql:3306/agent_db?charset=utf8mb4 REDIS_URL=redis://redis:6379/0 JWT_SECRET_KEY=${JWT_KEY} JWT_ALGORITHM=HS256 JWT_ACCESS_TOKEN_EXPIRE_MINUTES=30 CORS_ORIGINS=http://localhost:8038,http://localhost:3000 EXTERNAL_URL=${EXT_URL} DEEPSEEK_API_KEY=${DS_KEY} OPENAI_API_KEY=${OAI_KEY} HSTS_ENABLED=True WORKFLOW_MAX_STEPS_PER_RUN=2000 WORKFLOW_MAX_LLM_INVOCATIONS_PER_RUN=200 WORKFLOW_MAX_TOOL_CALLS_PER_RUN=500 MEMORY_PERSIST_DB_ENABLED=True EOF info "配置已写入 $ENV_FILE" fi # ─── 3. 构建与启动 ─────────────────────────────────────────────────────────── echo "" echo -e "${CYAN}── 构建镜像并启动服务 ──${NC}" echo "" # 导出环境变量供 docker compose 使用 export MYSQL_ROOT_PASSWORD export JWT_SECRET_KEY export SECRET_KEY export OPENAI_API_KEY export DEEPSEEK_API_KEY export EXTERNAL_URL info "正在构建镜像..." $COMPOSE -f "$COMPOSE_FILE" build --pull echo "" info "正在启动服务..." $COMPOSE -f "$COMPOSE_FILE" up -d echo "" info "等待服务就绪..." sleep 5 # ─── 4. 验证 ───────────────────────────────────────────────────────────────── echo "" echo -e "${CYAN}── 验证服务状态 ──${NC}" echo "" $COMPOSE -f "$COMPOSE_FILE" ps echo "" # 健康检查 BACKEND_OK=false for i in $(seq 1 30); do if curl -sf http://localhost:8037/docs >/dev/null 2>&1; then BACKEND_OK=true break fi sleep 2 done if $BACKEND_OK; then info "后端服务健康 (http://localhost:8037/docs)" else warn "后端服务可能尚未就绪,请稍后检查: docker compose -f docker-compose.prod.yml logs backend" fi # ─── 5. 完成 ───────────────────────────────────────────────────────────────── echo "" echo -e "${GREEN}╔══════════════════════════════════════════════╗${NC}" echo -e "${GREEN}║ 安装完成! ║${NC}" echo -e "${GREEN}╠══════════════════════════════════════════════╣${NC}" echo -e "${GREEN}║ 前端: http://localhost:8038 ║${NC}" echo -e "${GREEN}║ 后端: http://localhost:8037/docs ║${NC}" echo -e "${GREEN}║ 默认账号: admin / 123456 ║${NC}" echo -e "${GREEN}╠══════════════════════════════════════════════╣${NC}" echo -e "${GREEN}║ 管理命令: ║${NC}" echo -e "${GREEN}║ 查看日志: docker compose -f docker-compose.prod.yml logs -f${NC}" echo -e "${GREEN}║ 重启服务: docker compose -f docker-compose.prod.yml restart${NC}" echo -e "${GREEN}║ 停止服务: docker compose -f docker-compose.prod.yml down${NC}" echo -e "${GREEN}║ 升级: bash upgrade.sh ${NC}" echo -e "${GREEN}║ 卸载: bash uninstall.sh ${NC}" echo -e "${GREEN}╚══════════════════════════════════════════════╝${NC}" echo ""