#!/bin/bash # 情绪博物馆阿里云服务器优化部署脚本 # 适配要求:MySQL/Redis/Nacos直接安装,应用服务使用Docker # 分步骤执行,避免超时,记录密码到MD文件 # 作者: EmotionMuseum Team # 日期: 2025-07-13 set -e # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' PURPLE='\033[0;35m' CYAN='\033[0;36m' NC='\033[0m' # 服务器配置 SERVER_IP="47.111.10.27" SERVER_USER="root" MYSQL_ROOT_PASSWORD="123456" # 部署目录配置 PROGRAMS_DIR="/data/programs" BUILDS_DIR="/data/builds" WEB_DIR="/data/www/emotion-museum" LOGS_DIR="/data/logs/emotion-museum" CONFIG_FILE="/data/deployment_passwords.md" # 生成密码函数 generate_password() { echo $(openssl rand -base64 32 | tr -d "=+/" | cut -c1-20) } # 日志函数 log_info() { echo -e "${GREEN}[INFO]${NC} $1" } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } log_step() { echo -e "${BLUE}[STEP]${NC} $1" } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } log_debug() { echo -e "${CYAN}[DEBUG]${NC} $1" } # 远程执行命令 remote_exec() { local command="$1" local timeout="${2:-60}" ssh -o StrictHostKeyChecking=no -o ConnectTimeout="$timeout" -o ServerAliveInterval=30 -o ServerAliveCountMax=3 "${SERVER_USER}@${SERVER_IP}" "$command" } # 复制文件到服务器 remote_copy() { local local_path="$1" local remote_path="$2" scp -o StrictHostKeyChecking=no -r "$local_path" "${SERVER_USER}@${SERVER_IP}:$remote_path" } # 检查服务器连接 check_server_connection() { log_step "检查服务器连接..." if ! ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 "${SERVER_USER}@${SERVER_IP}" "echo 'Connected to server successfully'" &>/dev/null; then log_error "无法连接到服务器 ${SERVER_IP},请检查网络连接和SSH配置" exit 1 fi log_success "服务器连接正常" # 显示服务器基本信息 log_info "服务器信息:" remote_exec "echo ' 内核版本: '$(uname -r)" remote_exec "echo ' 当前用户: '$(whoami)" remote_exec "echo ' 当前时间: '$(date)" } # 创建服务器目录结构 setup_directories() { log_step "创建服务器目录结构..." remote_exec "mkdir -p ${PROGRAMS_DIR}/{java,maven,nodejs,nacos}" remote_exec "mkdir -p ${BUILDS_DIR}" remote_exec "mkdir -p ${WEB_DIR}" remote_exec "mkdir -p ${LOGS_DIR}/{mysql,redis,nacos,docker,nginx}" remote_exec "mkdir -p /data/backup" remote_exec "mkdir -p /data/ssl" log_success "目录结构创建完成" remote_exec "tree /data -L 2 2>/dev/null || ls -la /data" } # 安装基础软件包 install_basic_packages() { log_step "安装基础软件包..." remote_exec "yum update -y" remote_exec "yum install -y wget curl git unzip vim net-tools tree htop" log_success "基础软件包安装完成" } # 安装Docker install_docker() { log_step "安装Docker..." remote_exec " if ! command -v docker &> /dev/null; then echo '开始安装Docker...' curl -fsSL https://get.docker.com | sh systemctl start docker systemctl enable docker # 安装Docker Compose curl -L \"https://github.com/docker/compose/releases/download/1.29.2/docker-compose-\$(uname -s)-\$(uname -m)\" -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose ln -sf /usr/local/bin/docker-compose /usr/bin/docker-compose echo 'Docker和Docker Compose安装完成' docker --version docker-compose --version else echo 'Docker已安装: '$(docker --version) if ! command -v docker-compose &> /dev/null; then echo '安装Docker Compose...' curl -L \"https://github.com/docker/compose/releases/download/1.29.2/docker-compose-\$(uname -s)-\$(uname -m)\" -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose ln -sf /usr/local/bin/docker-compose /usr/bin/docker-compose fi echo 'Docker Compose: '$(docker-compose --version) fi " log_success "Docker安装检查完成" } # 安装Java环境 install_java() { log_step "安装Java环境..." remote_exec " if ! java -version 2>&1 | grep -q '17'; then echo '安装Java 17...' yum install -y java-17-openjdk java-17-openjdk-devel # 配置环境变量 echo 'export JAVA_HOME=/usr/lib/jvm/java-17-openjdk' >> /etc/profile echo 'export PATH=\$JAVA_HOME/bin:\$PATH' >> /etc/profile source /etc/profile echo 'Java 17安装完成' else echo 'Java 17已安装' fi java -version " log_success "Java环境检查完成" } # 安装Maven环境 install_maven() { log_step "安装Maven环境..." remote_exec " if ! command -v mvn &> /dev/null; then echo '安装Maven...' MAVEN_VERSION='3.9.5' cd /tmp wget https://archive.apache.org/dist/maven/maven-3/\${MAVEN_VERSION}/binaries/apache-maven-\${MAVEN_VERSION}-bin.tar.gz tar -xzf apache-maven-\${MAVEN_VERSION}-bin.tar.gz mv apache-maven-\${MAVEN_VERSION} ${PROGRAMS_DIR}/maven # 配置环境变量 echo 'export MAVEN_HOME=${PROGRAMS_DIR}/maven' >> /etc/profile echo 'export PATH=\$MAVEN_HOME/bin:\$PATH' >> /etc/profile source /etc/profile rm -f apache-maven-\${MAVEN_VERSION}-bin.tar.gz echo 'Maven安装完成' else echo 'Maven已安装' fi mvn -version 2>/dev/null || echo 'Maven需要重新登录生效' " log_success "Maven环境检查完成" } # 安装Node.js环境 install_nodejs() { log_step "安装Node.js环境..." remote_exec " if ! command -v node &> /dev/null; then echo '安装Node.js 18...' curl -fsSL https://rpm.nodesource.com/setup_18.x | bash - yum install -y nodejs # 配置npm镜像 npm config set registry https://registry.npmmirror.com echo 'Node.js安装完成' else echo 'Node.js已安装' fi node --version npm --version " log_success "Node.js环境检查完成" } # 验证MySQL连接 verify_mysql() { log_step "验证MySQL连接..." # 首先检查是否有Docker容器运行MySQL if remote_exec "docker ps | grep mysql > /dev/null"; then log_info "检测到Docker MySQL容器" if remote_exec "docker exec \$(docker ps | grep mysql | awk '{print \$1}') mysql -u root -p${MYSQL_ROOT_PASSWORD} -e 'SELECT 1;' &>/dev/null"; then log_success "Docker MySQL连接正常,密码正确" return 0 else log_error "Docker MySQL连接失败,请检查密码" return 1 fi # 检查本地MySQL服务 elif remote_exec "mysql -u root -p${MYSQL_ROOT_PASSWORD} -e 'SELECT 1;' &>/dev/null"; then log_success "本地MySQL连接正常,密码正确" return 0 else log_error "MySQL连接失败,请检查密码或MySQL服务状态" remote_exec "systemctl status mysqld || systemctl status mysql || echo 'No local MySQL service'" return 1 fi } # 配置MySQL数据库 setup_mysql() { log_step "配置MySQL数据库..." # 首先验证连接 if ! verify_mysql; then log_error "MySQL验证失败,请检查MySQL服务和密码" exit 1 fi # 创建应用数据库和用户 log_info "创建应用数据库和用户..." # 检查是否是Docker MySQL if remote_exec "docker ps | grep mysql > /dev/null"; then log_info "使用Docker MySQL容器" remote_exec " docker exec \$(docker ps | grep mysql | awk '{print \$1}') mysql -u root -p${MYSQL_ROOT_PASSWORD} -e \" CREATE DATABASE IF NOT EXISTS emotion_museum CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER IF NOT EXISTS 'emotion'@'%' IDENTIFIED BY 'EmotionDB2024!'; GRANT ALL PRIVILEGES ON emotion_museum.* TO 'emotion'@'%'; FLUSH PRIVILEGES; SELECT 'MySQL数据库配置完成' AS status; \" " else log_info "使用本地MySQL服务" remote_exec " mysql -u root -p${MYSQL_ROOT_PASSWORD} -e \" CREATE DATABASE IF NOT EXISTS emotion_museum CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER IF NOT EXISTS 'emotion'@'%' IDENTIFIED BY 'EmotionDB2024!'; GRANT ALL PRIVILEGES ON emotion_museum.* TO 'emotion'@'%'; FLUSH PRIVILEGES; SELECT 'MySQL数据库配置完成' AS status; \" " fi log_success "MySQL数据库配置完成" } # 配置Redis服务 setup_redis() { log_step "配置Redis服务..." # 检查是否已有Docker Redis容器运行 if remote_exec "docker ps | grep redis > /dev/null"; then log_info "检测到Docker Redis容器正在运行" # 获取Redis容器信息 REDIS_CONTAINER=$(remote_exec "docker ps | grep redis | awk '{print \$1}'") log_info "Redis容器ID: $REDIS_CONTAINER" # 测试Redis连接 if remote_exec "docker exec \$(docker ps | grep redis | awk '{print \$1}') redis-cli ping 2>/dev/null | grep -q PONG"; then log_success "Docker Redis服务正常运行" else log_warn "Docker Redis可能需要密码,尝试重启容器" remote_exec "docker restart \$(docker ps | grep redis | awk '{print \$1}')" sleep 5 fi # 记录Redis信息(从Docker环境变量获取) REDIS_PASSWORD=$(remote_exec "docker exec \$(docker ps | grep redis | awk '{print \$1}') env | grep REDIS_PASSWORD | cut -d'=' -f2 2>/dev/null || echo 'no-password'") echo "REDIS_PASSWORD=${REDIS_PASSWORD}" >> /tmp/passwords.txt log_success "Docker Redis配置确认完成" return 0 fi # 如果没有Docker Redis,安装本地Redis log_info "安装本地Redis服务..." # 生成Redis密码 REDIS_PASSWORD=$(generate_password) remote_exec " # 检查Redis是否已安装 if ! command -v redis-server &> /dev/null; then echo '安装Redis...' yum install -y redis else echo 'Redis已安装' fi # 配置Redis cp /etc/redis.conf /etc/redis.conf.backup 2>/dev/null || true sed -i 's/^# requirepass foobared/requirepass ${REDIS_PASSWORD}/' /etc/redis.conf sed -i 's/^bind 127.0.0.1/bind 0.0.0.0/' /etc/redis.conf # 启动Redis服务 systemctl start redis systemctl enable redis echo 'Redis配置完成,密码: ${REDIS_PASSWORD}' " # 记录Redis密码 echo "REDIS_PASSWORD=${REDIS_PASSWORD}" >> /tmp/passwords.txt log_success "本地Redis配置完成,密码已生成" } # 安装配置Nacos setup_nacos() { log_step "使用Docker安装配置Nacos..." # 检查是否已有Nacos容器运行 if remote_exec "docker ps | grep nacos > /dev/null"; then log_info "检测到Nacos容器正在运行" if remote_exec "curl -s http://localhost:8848/nacos > /dev/null"; then log_success "Nacos服务正常运行" return 0 else log_warn "Nacos容器存在但服务异常,重启容器" remote_exec "docker restart \$(docker ps | grep nacos | awk '{print \$1}')" sleep 10 fi fi log_info "创建Nacos Docker配置..." # 创建Nacos配置目录 remote_exec "mkdir -p ${PROGRAMS_DIR}/nacos/{conf,data,logs}" # 创建Nacos配置文件 cat > /tmp/nacos-application.properties << 'EOF' # Nacos配置文件 server.servlet.contextPath=/nacos server.port=8848 # 数据库配置 - 使用MySQL spring.datasource.platform=mysql db.num=1 db.url.0=jdbc:mysql://host.docker.internal:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai db.user.0=emotion db.password.0=EmotionDB2024! # JVM配置 nacos.inetutils.prefer-hostname-over-ip=false nacos.inetutils.ip-address=0.0.0.0 # 安全配置 nacos.security.ignore.urls=/,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-ui/public/**,/v1/auth/**,/v1/console/health/**,/actuator/**,/v1/console/server/** # 集群配置(单机模式) nacos.naming.distro.taskDispatchThreadCount=10 nacos.naming.distro.taskDispatchPeriod=200 nacos.naming.distro.batchSyncKeyCount=1000 nacos.naming.distro.initDataRatio=0.9 nacos.naming.distro.syncRetryDelay=5000 nacos.naming.data.warmup=true nacos.naming.expireInstance=true # 日志配置 logging.level.root=INFO logging.level.org.springframework=INFO logging.level.com.alibaba.nacos=INFO EOF # 上传配置文件 remote_copy "/tmp/nacos-application.properties" "${PROGRAMS_DIR}/nacos/conf/application.properties" rm /tmp/nacos-application.properties # 创建Nacos数据库 log_info "创建Nacos数据库..." if remote_exec "docker ps | grep mysql > /dev/null"; then remote_exec " docker exec \$(docker ps | grep mysql | awk '{print \$1}') mysql -u root -p${MYSQL_ROOT_PASSWORD} -e \" CREATE DATABASE IF NOT EXISTS nacos_config CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; GRANT ALL PRIVILEGES ON nacos_config.* TO 'emotion'@'%'; FLUSH PRIVILEGES; \" " fi # 启动Nacos容器 log_info "启动Nacos Docker容器..." remote_exec " # 停止可能存在的Nacos容器 docker stop emotion-nacos 2>/dev/null || true docker rm emotion-nacos 2>/dev/null || true # 启动新的Nacos容器 docker run -d \\ --name emotion-nacos \\ --restart=always \\ -p 8848:8848 \\ -p 9848:9848 \\ -p 9849:9849 \\ -e MODE=standalone \\ -e PREFER_HOST_MODE=hostname \\ -e SPRING_DATASOURCE_PLATFORM=mysql \\ -e MYSQL_SERVICE_HOST=host.docker.internal \\ -e MYSQL_SERVICE_PORT=3306 \\ -e MYSQL_SERVICE_DB_NAME=nacos_config \\ -e MYSQL_SERVICE_USER=emotion \\ -e MYSQL_SERVICE_PASSWORD=EmotionDB2024! \\ -e NACOS_AUTH_ENABLE=false \\ -v ${PROGRAMS_DIR}/nacos/conf:/home/nacos/conf \\ -v ${PROGRAMS_DIR}/nacos/data:/home/nacos/data \\ -v ${PROGRAMS_DIR}/nacos/logs:/home/nacos/logs \\ --add-host=host.docker.internal:host-gateway \\ nacos/nacos-server:v2.2.0 echo 'Nacos容器启动完成' " # 等待Nacos启动 log_info "等待Nacos服务启动..." sleep 30 # 验证Nacos服务 if remote_exec "curl -s http://localhost:8848/nacos > /dev/null"; then log_success "Nacos服务启动成功" else log_warn "Nacos服务可能还在启动中,请稍后检查" fi log_success "Docker Nacos安装配置完成" } # 上传构建产物 upload_artifacts() { log_step "上传构建产物..." # 检查构建产物是否存在 if [ ! -d "build-output" ]; then log_error "构建产物不存在,请先运行构建命令" log_info "可以运行: ./package.sh 或 mvn clean package" exit 1 fi # 上传JAR文件 if [ -d "build-output/jars" ]; then log_info "上传JAR文件..." for jar in build-output/jars/*.jar; do if [ -f "$jar" ]; then remote_copy "$jar" "${BUILDS_DIR}/" log_info "已上传: $(basename $jar)" fi done fi # 上传前端文件 if [ -d "build-output/web" ]; then log_info "上传前端文件..." remote_exec "rm -rf ${WEB_DIR}/*" # 直接上传整个目录 remote_copy "build-output/web/" "${WEB_DIR}/" log_info "前端文件上传完成" fi # 上传数据库脚本 if [ -f "backend/mysql_emotion_museum_final.sql" ]; then remote_copy "backend/mysql_emotion_museum_final.sql" "/tmp/" log_info "数据库脚本上传完成" fi log_success "构建产物上传完成" } # 导入数据库 import_database() { log_step "导入数据库..." if ! remote_exec "[ -f /tmp/mysql_emotion_museum_final.sql ]"; then log_error "数据库脚本不存在,跳过导入" return 1 fi # 检查是否是Docker MySQL if remote_exec "docker ps | grep mysql > /dev/null"; then log_info "使用Docker MySQL导入数据库..." remote_exec " echo '开始导入数据库到Docker MySQL...' docker exec -i \$(docker ps | grep mysql | awk '{print \$1}') mysql -u root -p${MYSQL_ROOT_PASSWORD} emotion_museum < /tmp/mysql_emotion_museum_final.sql echo '数据库导入完成' # 验证导入结果 docker exec \$(docker ps | grep mysql | awk '{print \$1}') mysql -u root -p${MYSQL_ROOT_PASSWORD} emotion_museum -e 'SHOW TABLES;' " else log_info "使用本地MySQL导入数据库..." remote_exec " echo '开始导入数据库到本地MySQL...' mysql -u root -p${MYSQL_ROOT_PASSWORD} emotion_museum < /tmp/mysql_emotion_museum_final.sql echo '数据库导入完成' # 验证导入结果 mysql -u root -p${MYSQL_ROOT_PASSWORD} emotion_museum -e 'SHOW TABLES;' " fi log_success "数据库导入完成" } # 创建应用启动脚本(不使用Docker) create_app_scripts() { log_step "创建应用启动脚本..." # 创建启动脚本 cat > /tmp/start-services.sh << 'EOF' #!/bin/bash # 情绪博物馆应用服务启动脚本 BUILDS_DIR="/data/builds" LOGS_DIR="/data/logs/emotion-museum" # 创建日志目录 mkdir -p ${LOGS_DIR}/{gateway,ai,user} # 设置环境变量 export SPRING_PROFILES_ACTIVE=prod export NACOS_SERVER_ADDR=localhost:8848 export MYSQL_HOST=localhost export MYSQL_PORT=3306 export MYSQL_DATABASE=emotion_museum export MYSQL_USERNAME=emotion export MYSQL_PASSWORD=EmotionDB2024! export REDIS_HOST=localhost export REDIS_PORT=6379 export COZE_API_TOKEN=pat_GCR4qKzqpf90wMCvKsldMrB18KG3QsLDci65bZthssKsbLxu8X70BKYumleDcabO export TZ=Asia/Shanghai # 停止可能运行的服务 pkill -f emotion-gateway || true pkill -f emotion-ai || true pkill -f emotion-user || true sleep 5 # 启动网关服务 echo "启动网关服务..." nohup java -jar ${BUILDS_DIR}/emotion-gateway-1.0.0.jar \ --server.port=9000 \ --spring.profiles.active=prod \ --spring.cloud.nacos.discovery.server-addr=${NACOS_SERVER_ADDR} \ --spring.cloud.nacos.discovery.enabled=true \ --spring.cloud.nacos.discovery.namespace=public \ --spring.cloud.nacos.discovery.group=DEFAULT_GROUP \ --spring.redis.host=${REDIS_HOST} \ --spring.redis.port=${REDIS_PORT} \ > ${LOGS_DIR}/gateway/app.log 2>&1 & sleep 10 # 启动AI服务 echo "启动AI服务..." nohup java -jar ${BUILDS_DIR}/emotion-ai-1.0.0.jar \ --server.port=9002 \ --spring.profiles.active=prod \ --spring.main.allow-bean-definition-overriding=true \ --spring.cloud.nacos.discovery.server-addr=${NACOS_SERVER_ADDR} \ --spring.cloud.nacos.discovery.enabled=true \ --spring.cloud.nacos.discovery.namespace=public \ --spring.cloud.nacos.discovery.group=DEFAULT_GROUP \ --spring.datasource.url=jdbc:mysql://${MYSQL_HOST}:${MYSQL_PORT}/${MYSQL_DATABASE}?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai \ --spring.datasource.username=${MYSQL_USERNAME} \ --spring.datasource.password=${MYSQL_PASSWORD} \ --spring.redis.host=${REDIS_HOST} \ --spring.redis.port=${REDIS_PORT} \ --coze.api.token=${COZE_API_TOKEN} \ > ${LOGS_DIR}/ai/app.log 2>&1 & sleep 10 # 启动用户服务 echo "启动用户服务..." nohup java -jar ${BUILDS_DIR}/emotion-user-1.0.0.jar \ --server.port=9001 \ --spring.profiles.active=prod \ --spring.main.allow-bean-definition-overriding=true \ --spring.cloud.nacos.discovery.server-addr=${NACOS_SERVER_ADDR} \ --spring.cloud.nacos.discovery.enabled=true \ --spring.cloud.nacos.discovery.namespace=public \ --spring.cloud.nacos.discovery.group=DEFAULT_GROUP \ --spring.datasource.url=jdbc:mysql://${MYSQL_HOST}:${MYSQL_PORT}/${MYSQL_DATABASE}?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai \ --spring.datasource.username=${MYSQL_USERNAME} \ --spring.datasource.password=${MYSQL_PASSWORD} \ --spring.redis.host=${REDIS_HOST} \ --spring.redis.port=${REDIS_PORT} \ > ${LOGS_DIR}/user/app.log 2>&1 & echo "所有服务启动完成" echo "查看服务状态: ps aux | grep emotion" echo "查看日志: tail -f ${LOGS_DIR}/*/app.log" EOF # 创建停止脚本 cat > /tmp/stop-services.sh << 'EOF' #!/bin/bash echo "停止情绪博物馆应用服务..." pkill -f emotion-gateway && echo "网关服务已停止" pkill -f emotion-ai && echo "AI服务已停止" pkill -f emotion-user && echo "用户服务已停止" echo "所有服务已停止" EOF # 上传脚本 remote_copy "/tmp/start-services.sh" "${BUILDS_DIR}/start-services.sh" remote_copy "/tmp/stop-services.sh" "${BUILDS_DIR}/stop-services.sh" # 设置执行权限 remote_exec "chmod +x ${BUILDS_DIR}/start-services.sh ${BUILDS_DIR}/stop-services.sh" # 清理临时文件 rm /tmp/start-services.sh /tmp/stop-services.sh log_success "应用启动脚本创建完成" } # 配置Nginx setup_nginx() { log_step "配置Nginx..." remote_exec " # 安装Nginx if ! command -v nginx &> /dev/null; then yum install -y nginx fi # 备份原配置 cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup # 创建新的Nginx配置 cat > /etc/nginx/nginx.conf << 'NGINX_EOF' user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid; events { worker_connections 1024; } http { log_format main '\$remote_addr - \$remote_user [\$time_local] \"\$request\" ' '\$status \$body_bytes_sent \"\$http_referer\" ' '\"\$http_user_agent\" \"\$http_x_forwarded_for\"'; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; # 前端应用 server { listen 80; server_name _; # 情绪博物馆前端应用 location /emotion-museum { alias ${WEB_DIR}; index index.html; try_files \$uri \$uri/ /emotion-museum/index.html; } # 根路径重定向到情绪博物馆 location = / { return 301 /emotion-museum/; } # API代理到网关 location /api/ { proxy_pass http://127.0.0.1:9000/api/; proxy_set_header Host \$host; proxy_set_header X-Real-IP \$remote_addr; proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto \$scheme; proxy_connect_timeout 30s; proxy_send_timeout 30s; proxy_read_timeout 30s; } # 静态资源缓存 location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { expires 1y; add_header Cache-Control \"public, no-transform\"; } # 健康检查 location /health { access_log off; return 200 'healthy'; add_header Content-Type text/plain; } } } NGINX_EOF # 启动Nginx systemctl start nginx systemctl enable nginx echo 'Nginx配置完成' " log_success "Nginx配置完成" } # 启动应用服务 start_app_services() { log_step "启动应用服务..." # 使用脚本启动服务 remote_exec " cd ${BUILDS_DIR} # 执行启动脚本 bash start-services.sh echo '应用服务启动完成' " # 等待服务启动 sleep 15 # 检查服务状态 log_info "检查服务状态..." remote_exec "ps aux | grep -E 'emotion-(gateway|ai|user)' | grep -v grep || echo '没有找到运行的服务'" log_success "应用服务启动完成" } # 创建密码记录文件 create_password_record() { log_step "创建密码记录文件..." # 读取临时密码文件 REDIS_PASSWORD="" if [ -f "/tmp/passwords.txt" ]; then REDIS_PASSWORD=$(grep "REDIS_PASSWORD" /tmp/passwords.txt | cut -d'=' -f2) fi cat > /tmp/deployment_passwords.md << EOF # 情绪博物馆部署密码记录 ## 服务器信息 - 服务器IP: ${SERVER_IP} - 部署时间: $(date '+%Y-%m-%d %H:%M:%S') - 部署用户: ${SERVER_USER} ## 数据库配置 ### MySQL - 端口: 3306 - Root用户: root - Root密码: ${MYSQL_ROOT_PASSWORD} - 应用数据库: emotion_museum - 应用用户: emotion - 应用密码: EmotionDB2024! ### Redis - 端口: 6379 - 密码: ${REDIS_PASSWORD:-"未设置或生成失败"} ## 服务端口配置 - Nginx: 80 - MySQL: 3306 - Redis: 6379 - Nacos: 8848 - 网关服务: 9000 - 用户服务: 9001 - AI服务: 9002 ## 访问地址 - 前端应用: http://${SERVER_IP} - API网关: http://${SERVER_IP}:9000 - Nacos控制台: http://${SERVER_IP}:8848/nacos - 用户名: nacos - 密码: nacos ## API配置 - Coze API Token: pat_GCR4qKzqpf90wMCvKsldMrB18KG3QsLDci65bZthssKsbLxu8X70BKYumleDcabO ## 目录结构 - 程序目录: ${PROGRAMS_DIR} - 构建目录: ${BUILDS_DIR} - 前端目录: ${WEB_DIR} - 日志目录: ${LOGS_DIR} - 备份目录: /data/backup ## 管理命令 \`\`\`bash # 查看服务状态 systemctl status mysqld redis nacos nginx docker ps # 查看应用日志 docker logs -f emotion-gateway docker logs -f emotion-ai docker logs -f emotion-user # 重启服务 systemctl restart mysqld redis nacos nginx docker-compose -f ${BUILDS_DIR}/docker-compose.yml restart # 停止所有服务 docker-compose -f ${BUILDS_DIR}/docker-compose.yml down systemctl stop nginx redis mysqld ${PROGRAMS_DIR}/nacos/bin/shutdown.sh \`\`\` ## 备份命令 \`\`\`bash # 数据库备份 mysqldump -u root -p${MYSQL_ROOT_PASSWORD} emotion_museum > /data/backup/emotion_museum_\$(date +%Y%m%d_%H%M%S).sql # 配置备份 tar -czf /data/backup/config_\$(date +%Y%m%d_%H%M%S).tar.gz /etc/nginx /etc/redis.conf ${PROGRAMS_DIR}/nacos/conf \`\`\` ## 安全提醒 ⚠️ 重要提醒: 1. 请及时修改默认密码 2. 建议配置防火墙规则 3. 定期备份数据库 4. 监控服务器资源使用情况 ## 更新记录 - $(date '+%Y-%m-%d %H:%M:%S'): 初始部署完成 --- **此文件包含敏感信息,请妥善保管!** EOF # 上传密码记录文件 remote_copy "/tmp/deployment_passwords.md" "${CONFIG_FILE}" rm /tmp/deployment_passwords.md # 清理临时密码文件 rm -f /tmp/passwords.txt log_success "密码记录文件已创建: ${CONFIG_FILE}" } # 健康检查 health_check() { log_step "执行健康检查..." sleep 30 # 等待服务启动 log_info "检查基础服务状态..." remote_exec " echo '=== 系统服务状态 ===' systemctl is-active mysqld && echo '✅ MySQL: 运行中' || echo '❌ MySQL: 异常' systemctl is-active redis && echo '✅ Redis: 运行中' || echo '❌ Redis: 异常' systemctl is-active nginx && echo '✅ Nginx: 运行中' || echo '❌ Nginx: 异常' pgrep -f nacos > /dev/null && echo '✅ Nacos: 运行中' || echo '❌ Nacos: 异常' echo '' echo '=== Docker服务状态 ===' docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}' echo '' echo '=== 端口监听状态 ===' netstat -tlnp | grep -E ':(80|3306|6379|8848|9000|9001|9002)' | awk '{print \$1\" \"\$4}' | sort " log_info "HTTP接口测试..." # 测试前端 if remote_exec "curl -s -o /dev/null -w '%{http_code}' http://localhost:80 | grep -q 200"; then log_success "✅ 前端应用访问正常" else log_warn "❌ 前端应用访问异常" fi # 测试Nacos if remote_exec "curl -s -o /dev/null -w '%{http_code}' http://localhost:8848/nacos | grep -q 200"; then log_success "✅ Nacos控制台访问正常" else log_warn "❌ Nacos控制台访问异常" fi # 测试网关 sleep 10 # 额外等待网关启动 if remote_exec "curl -s -o /dev/null -w '%{http_code}' http://localhost:9000/actuator/health 2>/dev/null | grep -q 200"; then log_success "✅ API网关访问正常" else log_warn "❌ API网关访问异常(可能还在启动中)" fi log_success "健康检查完成" } # 显示部署结果 show_deployment_result() { echo "" echo "🎉 情绪博物馆部署完成!" echo "" echo "📱 访问地址:" echo " 前端应用: http://${SERVER_IP}" echo " API网关: http://${SERVER_IP}:9000" echo " Nacos: http://${SERVER_IP}:8848/nacos" echo "" echo "📁 重要文件:" echo " 密码记录: ${CONFIG_FILE}" echo " 应用目录: ${BUILDS_DIR}" echo " 前端目录: ${WEB_DIR}" echo " 日志目录: ${LOGS_DIR}" echo "" echo "🔧 管理命令:" echo " ssh ${SERVER_USER}@${SERVER_IP}" echo " docker-compose -f ${BUILDS_DIR}/docker-compose.yml logs -f" echo " systemctl status mysqld redis nacos nginx" echo "" echo "⚠️ 重要提醒:" echo " 1. 密码信息已保存到服务器 ${CONFIG_FILE} 文件中" echo " 2. 请及时修改默认密码" echo " 3. 建议配置防火墙规则" echo " 4. 定期备份数据库" echo "" } # 显示帮助信息 show_help() { echo "情绪博物馆阿里云部署脚本" echo "" echo "用法: $0 [选项]" echo "" echo "选项:" echo " check - 检查服务器连接和环境" echo " env - 安装基础环境(Java、Maven、Node.js、Docker)" echo " mysql - 配置MySQL数据库" echo " redis - 配置Redis服务" echo " nacos - 安装配置Nacos" echo " upload - 上传构建产物" echo " import-db - 导入数据库" echo " deploy - 部署应用服务" echo " nginx - 配置Nginx" echo " health - 健康检查" echo " passwords - 创建密码记录文件" echo " all - 完整部署(默认)" echo " help - 显示此帮助信息" echo "" echo "分步骤部署示例:" echo " $0 check # 1. 检查服务器连接" echo " $0 env # 2. 安装基础环境" echo " $0 mysql # 3. 配置MySQL" echo " $0 redis # 4. 配置Redis" echo " $0 nacos # 5. 安装Nacos" echo " $0 upload # 6. 上传构建产物" echo " $0 import-db # 7. 导入数据库" echo " $0 deploy # 8. 部署应用服务" echo " $0 nginx # 9. 配置Nginx" echo " $0 passwords # 10. 创建密码记录" echo " $0 health # 11. 健康检查" echo "" echo "一键部署:" echo " $0 all # 完整部署所有组件" echo "" } # 主函数入口 main() { case "${1:-all}" in "check") check_server_connection ;; "env") check_server_connection setup_directories install_basic_packages install_docker install_java install_maven install_nodejs log_success "基础环境安装完成!" echo "下一步: $0 mysql" ;; "mysql") check_server_connection setup_mysql log_success "MySQL配置完成!" echo "下一步: $0 redis" ;; "redis") check_server_connection setup_redis log_success "Redis配置完成!" echo "下一步: $0 nacos" ;; "nacos") check_server_connection setup_nacos log_success "Nacos安装完成!" echo "下一步: $0 upload" ;; "upload") check_server_connection upload_artifacts log_success "构建产物上传完成!" echo "下一步: $0 import-db" ;; "import-db") check_server_connection import_database log_success "数据库导入完成!" echo "下一步: $0 deploy" ;; "deploy") check_server_connection create_app_scripts start_app_services log_success "应用服务部署完成!" echo "下一步: $0 nginx" ;; "nginx") check_server_connection setup_nginx log_success "Nginx配置完成!" echo "下一步: $0 passwords" ;; "passwords") check_server_connection create_password_record log_success "密码记录创建完成!" echo "下一步: $0 health" ;; "health") check_server_connection health_check show_deployment_result ;; "help") show_help ;; "all") echo "🚀 开始完整部署情绪博物馆到阿里云服务器..." echo "" # 完整部署流程 check_server_connection setup_directories install_basic_packages install_docker install_java install_maven install_nodejs setup_mysql setup_redis setup_nacos upload_artifacts import_database create_app_scripts start_app_services setup_nginx create_password_record health_check show_deployment_result ;; *) echo "未知选项: $1" show_help exit 1 ;; esac } # 执行主函数 main "$@"