#!/bin/bash # 情绪博物馆阿里云服务器简化部署脚本 # 分步骤执行,避免超时问题 set -e # 颜色定义 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' 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" CONFIG_FILE="/data/deployment_config.md" # 日志函数 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" } # 远程执行命令 remote_exec() { local command="$1" ssh -o StrictHostKeyChecking=no "${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_info "服务器连接正常" } # 创建服务器目录结构 setup_directories() { log_step "创建服务器目录结构..." remote_exec "mkdir -p ${PROGRAMS_DIR}/{mysql,redis,nacos,java,maven,nodejs}" remote_exec "mkdir -p ${BUILDS_DIR}" remote_exec "mkdir -p ${WEB_DIR}" remote_exec "mkdir -p /data/logs/{mysql,redis,nacos,docker,nginx}" remote_exec "mkdir -p /data/backup" log_info "目录结构创建完成" } # 安装基础软件 install_basic_packages() { log_step "安装基础软件包..." remote_exec "yum update -y && yum install -y wget curl git unzip vim net-tools" log_info "基础软件包安装完成" } # 安装Docker install_docker() { log_step "安装Docker..." remote_exec " if ! command -v docker &> /dev/null; then curl -fsSL https://get.docker.com | sh systemctl start docker systemctl enable docker echo 'Docker安装完成' else echo 'Docker已安装' fi " log_info "Docker安装检查完成" } # 安装Java install_java() { log_step "安装Java 17..." remote_exec " if ! java -version 2>&1 | grep -q '17'; then 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 " log_info "Java安装检查完成" } # 安装Node.js install_nodejs() { log_step "安装Node.js..." remote_exec " if ! command -v node &> /dev/null; then curl -fsSL https://rpm.nodesource.com/setup_18.x | bash - yum install -y nodejs npm config set registry https://registry.npmmirror.com echo 'Node.js安装完成' else echo 'Node.js已安装' fi " log_info "Node.js安装检查完成" } # 安装和配置MySQL setup_mysql() { log_step "配置MySQL..." # 检查MySQL是否已运行 if remote_exec "systemctl is-active --quiet mysqld 2>/dev/null && mysql -u root -p${MYSQL_ROOT_PASSWORD} -e 'SELECT 1;' &>/dev/null"; then log_info "MySQL已配置且运行正常" return 0 fi log_info "配置MySQL数据库..." remote_exec " # 测试连接 if mysql -u root -p${MYSQL_ROOT_PASSWORD} -e 'SELECT 1;' &>/dev/null; then echo 'MySQL连接正常' # 创建应用数据库 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; \" echo 'MySQL数据库和用户创建完成' else echo 'MySQL连接失败,请检查密码或安装状态' exit 1 fi " log_info "MySQL配置完成" } # 安装和配置Redis setup_redis() { log_step "配置Redis..." if remote_exec "systemctl is-active --quiet redis 2>/dev/null"; then log_info "Redis已运行" return 0 fi remote_exec " # 安装Redis if ! command -v redis-server &> /dev/null; then yum install -y epel-release yum install -y redis fi # 基本配置 sed -i 's/^bind 127.0.0.1/bind 0.0.0.0/' /etc/redis.conf # 启动服务 systemctl start redis systemctl enable redis echo 'Redis配置完成' " log_info "Redis配置完成" } # 安装Nacos setup_nacos() { log_step "配置Nacos..." if remote_exec "pgrep -f nacos > /dev/null"; then log_info "Nacos已运行" return 0 fi remote_exec " NACOS_DIR='${PROGRAMS_DIR}/nacos' if [ ! -d \"\${NACOS_DIR}\" ]; then cd /tmp if [ ! -f nacos-server-2.2.0.tar.gz ]; then wget https://github.com/alibaba/nacos/releases/download/2.2.0/nacos-server-2.2.0.tar.gz fi tar -xzf nacos-server-2.2.0.tar.gz mv nacos \${NACOS_DIR} # 配置单机模式 cd \${NACOS_DIR}/conf cp application.properties application.properties.backup cat > application.properties << 'EOF' server.servlet.contextPath=/nacos server.port=8848 nacos.security.ignore.urls=/,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-ui/public/**,/v1/auth/**,/v1/console/health/**,/actuator/**,/v1/console/server/** EOF fi # 启动Nacos cd \${NACOS_DIR}/bin bash startup.sh -m standalone echo 'Nacos配置完成' " log_info "Nacos配置完成" } # 上传构建产物 upload_artifacts() { log_step "上传构建产物..." # 检查构建产物是否存在 if [ ! -d "build-output" ]; then log_error "构建产物不存在,请先运行: ./deploy-aliyun.sh build" exit 1 fi # 上传JAR文件 if [ -d "build-output/jars" ]; then 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 remote_exec "rm -rf ${WEB_DIR}/*" for file in build-output/web/*; do if [ -e "$file" ]; then remote_copy "$file" "${WEB_DIR}/" fi done 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_info "构建产物上传完成" } # 导入数据库 import_database() { log_step "导入数据库..." remote_exec " if [ -f /tmp/mysql_emotion_museum_final.sql ]; then mysql -u root -p${MYSQL_ROOT_PASSWORD} emotion_museum < /tmp/mysql_emotion_museum_final.sql echo '数据库导入完成' else echo '数据库脚本不存在' exit 1 fi " log_info "数据库导入完成" } # 创建Docker配置 create_docker_config() { log_step "创建Docker配置..." # 创建应用Docker Compose文件 cat > /tmp/docker-compose-app.yml << 'EOF' version: '3.8' services: # 网关服务 gateway: image: openjdk:17-jre-slim container_name: emotion-gateway restart: always ports: - "9000:9000" environment: SPRING_PROFILES_ACTIVE: prod TZ: Asia/Shanghai volumes: - /data/builds/emotion-gateway-1.0.0.jar:/app/app.jar - /data/logs/docker/gateway:/app/logs working_dir: /app command: ["java", "-jar", "app.jar"] extra_hosts: - "host.docker.internal:host-gateway" networks: - emotion-network # AI服务 ai-service: image: openjdk:17-jre-slim container_name: emotion-ai restart: always ports: - "9002:9002" environment: SPRING_PROFILES_ACTIVE: prod TZ: Asia/Shanghai volumes: - /data/builds/emotion-ai-1.0.0.jar:/app/app.jar - /data/logs/docker/ai:/app/logs working_dir: /app command: ["java", "-jar", "app.jar"] extra_hosts: - "host.docker.internal:host-gateway" networks: - emotion-network # 用户服务 user-service: image: openjdk:17-jre-slim container_name: emotion-user restart: always ports: - "9001:9001" environment: SPRING_PROFILES_ACTIVE: prod TZ: Asia/Shanghai volumes: - /data/builds/emotion-user-1.0.0.jar:/app/app.jar - /data/logs/docker/user:/app/logs working_dir: /app command: ["java", "-jar", "app.jar"] extra_hosts: - "host.docker.internal:host-gateway" networks: - emotion-network networks: emotion-network: driver: bridge EOF # 上传配置文件 remote_copy "/tmp/docker-compose-app.yml" "${BUILDS_DIR}/docker-compose.yml" rm /tmp/docker-compose-app.yml log_info "Docker配置创建完成" } # 配置Nginx setup_nginx() { log_step "配置Nginx..." remote_exec " # 安装Nginx if ! command -v nginx &> /dev/null; then yum install -y nginx fi # 创建配置文件 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 ${SERVER_IP}; root ${WEB_DIR}; index index.html; # 前端路由 location / { try_files \$uri \$uri/ /index.html; } # API代理 location /api/ { proxy_pass http://127.0.0.1:9000/; 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; } # 静态资源缓存 location ~* \\.(js|css|png|jpg|jpeg|gif|ico|svg)$ { expires 1y; add_header Cache-Control \"public, no-transform\"; } } } NGINX_EOF # 启动Nginx systemctl start nginx systemctl enable nginx echo 'Nginx配置完成' " log_info "Nginx配置完成" } # 启动应用服务 start_app_services() { log_step "启动应用服务..." remote_exec " cd ${BUILDS_DIR} # 安装Docker Compose(如果没有) if ! command -v docker-compose &> /dev/null; then 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 fi # 启动应用服务 docker-compose up -d echo '应用服务启动完成' " log_info "应用服务启动完成" } # 健康检查 health_check() { log_step "执行健康检查..." sleep 30 # 等待服务启动 log_info "检查基础服务..." remote_exec "systemctl is-active mysqld redis nginx || true" log_info "检查Nacos服务..." remote_exec "pgrep -f nacos || echo 'Nacos未运行'" log_info "检查Docker服务..." remote_exec "docker ps" log_info "检查端口监听..." remote_exec "netstat -tlnp | grep -E ':(80|3306|6379|8848|9000|9001|9002)' || true" # HTTP健康检查 log_info "HTTP接口测试..." if remote_exec "curl -s -o /dev/null -w '%{http_code}' http://localhost:80 | grep -q 200"; then log_info "✅ 前端应用正常" else log_warn "❌ 前端应用异常" fi if remote_exec "curl -s -o /dev/null -w '%{http_code}' http://localhost:8848/nacos | grep -q 200"; then log_info "✅ Nacos控制台正常" else log_warn "❌ Nacos控制台异常" fi log_info "健康检查完成" } # 创建配置记录 create_config_record() { log_step "创建配置记录..." cat > /tmp/deployment_config.md << EOF # 情绪博物馆部署配置记录 ## 服务器信息 - 服务器IP: ${SERVER_IP} - 部署时间: $(date '+%Y-%m-%d %H:%M:%S') ## 服务配置 ### 数据库 - MySQL端口: 3306 - root密码: ${MYSQL_ROOT_PASSWORD} - 应用数据库: emotion_museum - 应用用户: emotion/EmotionDB2024! ### 服务端口 - Redis: 6379 - Nacos: 8848 - 网关: 9000 - 用户服务: 9001 - AI服务: 9002 - Nginx: 80 ## 访问地址 - 前端应用: http://${SERVER_IP} - API网关: http://${SERVER_IP}:9000 - Nacos控制台: http://${SERVER_IP}:8848/nacos (nacos/nacos) ## 管理命令 \`\`\`bash # 查看服务状态 systemctl status mysqld redis nginx docker ps # 查看应用日志 docker logs -f emotion-gateway docker logs -f emotion-ai docker logs -f emotion-user # 重启服务 systemctl restart mysqld redis 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} - 构建目录: ${BUILDS_DIR} - 前端目录: ${WEB_DIR} - 日志目录: /data/logs - 备份目录: /data/backup EOF remote_copy "/tmp/deployment_config.md" "${CONFIG_FILE}" rm /tmp/deployment_config.md log_info "配置记录已创建: ${CONFIG_FILE}" } # 显示部署结果 show_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 "" echo "🔧 管理命令:" echo " ssh ${SERVER_USER}@${SERVER_IP}" echo " docker-compose -f ${BUILDS_DIR}/docker-compose.yml logs -f" echo "" } # 主部署流程 main() { echo "🚀 开始部署情绪博物馆到阿里云服务器..." echo "" check_server_connection setup_directories install_basic_packages install_docker install_java install_nodejs setup_mysql setup_redis setup_nacos upload_artifacts import_database create_docker_config setup_nginx start_app_services create_config_record health_check show_result } # 命令行参数处理 case "${1:-}" in "env") log_info "仅安装环境..." check_server_connection setup_directories install_basic_packages install_docker install_java install_nodejs setup_mysql setup_redis setup_nacos ;; "app") log_info "仅部署应用..." check_server_connection upload_artifacts import_database create_docker_config setup_nginx start_app_services health_check ;; "health") check_server_connection health_check ;; *) main ;; esac