From 363e17385bb7dab0b060895d62b579daa49b0bf9 Mon Sep 17 00:00:00 2001 From: Peanut Date: Sun, 17 May 2026 16:56:57 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E5=90=88=E5=B9=B6=E4=B8=89?= =?UTF-8?q?=E4=B8=AA=E9=83=A8=E7=BD=B2=E8=84=9A=E6=9C=AC=E4=B8=BA=E7=BB=9F?= =?UTF-8?q?=E4=B8=80=E7=9A=84=20deploy.sh?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 deploy.sh 作为统一部署入口,支持 ssl|backend|frontend|admin|life-script|nginx|verify|all - deploy-all.sh / deploy-to-prod.sh / deploy-domain.sh 改为向后兼容的 wrapper - 消除原脚本中后端/前端/管理后台部署逻辑的重复 - 统一使用各子目录的 deploy.sh/deploy.py 脚本,避免重复构建逻辑 - 新增 verify 子命令用于部署后验证 Co-Authored-By: Claude Opus 4.7 --- deploy-all.sh | 251 +------------------------------------------- deploy-domain.sh | 104 +------------------ deploy-to-prod.sh | 254 +-------------------------------------------- deploy.sh | 258 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 267 insertions(+), 600 deletions(-) create mode 100644 deploy.sh diff --git a/deploy-all.sh b/deploy-all.sh index 4554904..9d2056e 100755 --- a/deploy-all.sh +++ b/deploy-all.sh @@ -1,250 +1,5 @@ #!/bin/bash - -# 情绪博物馆 - 一键式部署脚本 -# 同时部署后端、前端和管理后台到远程服务器 101.200.208.45 -# 使用方法: bash deploy-all.sh [backend|frontend|admin|all] -# 默认部署所有服务 - -set -e - -# 颜色定义 -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color - -# 日志函数 -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_section() { - echo "" - echo -e "${BLUE}╔════════════════════════════════════════════════════════════════╗${NC}" - echo -e "${BLUE}║${NC} $1" - echo -e "${BLUE}╚════════════════════════════════════════════════════════════════╝${NC}" - echo "" -} - -# 获取脚本所在目录 -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -cd "$SCRIPT_DIR" - -# 部署类型(默认为all) -DEPLOY_TYPE="${1:-all}" - -# 验证部署类型 -if [[ ! "$DEPLOY_TYPE" =~ ^(backend|frontend|admin|all)$ ]]; then - log_error "无效的部署类型: $DEPLOY_TYPE" - echo "使用方法: bash deploy-all.sh [backend|frontend|admin|all]" - exit 1 -fi - -# 记录开始时间 -START_TIME=$(date +%s) - -# ============================================================================ -# 部署后端 -# ============================================================================ -deploy_backend() { - log_section "开始部署后端服务" - - if [ ! -f "backend-single/deploy.sh" ]; then - log_error "后端部署脚本不存在: backend-single/deploy.sh" - return 1 - fi - - log_info "执行后端部署脚本..." - cd backend-single - - if bash deploy.sh remote; then - log_info "✅ 后端部署成功" - cd .. - return 0 - else - log_error "❌ 后端部署失败" - cd .. - return 1 - fi -} - -# ============================================================================ -# 部署前端 -# ============================================================================ -deploy_frontend() { - log_section "开始部署前端应用" - - if [ ! -f "web/deploy.sh" ]; then - log_error "前端部署脚本不存在: web/deploy.sh" - return 1 - fi - - log_info "执行前端部署脚本..." - cd web - - if bash deploy.sh; then - log_info "✅ 前端部署成功" - cd .. - return 0 - else - log_error "❌ 前端部署失败" - cd .. - return 1 - fi -} - -# ============================================================================ -# 部署管理后台 -# ============================================================================ -deploy_admin() { - log_section "开始部署管理后台" - - if [ ! -f "web-admin/deploy.sh" ]; then - log_error "管理后台部署脚本不存在: web-admin/deploy.sh" - return 1 - fi - - log_info "执行管理后台部署脚本..." - cd web-admin - - if bash deploy.sh; then - log_info "✅ 管理后台部署成功" - cd .. - return 0 - else - log_error "❌ 管理后台部署失败" - cd .. - return 1 - fi -} - -# ============================================================================ -# 主程序 -# ============================================================================ - -log_section "情绪博物馆 - 一键式部署" -log_info "部署类型: $DEPLOY_TYPE" -log_info "部署时间: $(date '+%Y-%m-%d %H:%M:%S')" - -BACKEND_SUCCESS=true -FRONTEND_SUCCESS=true -ADMIN_SUCCESS=true - -# 执行部署 -case "$DEPLOY_TYPE" in - backend) - if ! deploy_backend; then - BACKEND_SUCCESS=false - fi - ;; - frontend) - if ! deploy_frontend; then - FRONTEND_SUCCESS=false - fi - ;; - admin) - if ! deploy_admin; then - ADMIN_SUCCESS=false - fi - ;; - all) - if ! deploy_backend; then - BACKEND_SUCCESS=false - fi - - if ! deploy_frontend; then - FRONTEND_SUCCESS=false - fi - - if ! deploy_admin; then - ADMIN_SUCCESS=false - fi - ;; -esac - -# ============================================================================ -# 部署总结 -# ============================================================================ - -END_TIME=$(date +%s) -DURATION=$((END_TIME - START_TIME)) - -log_section "部署完成总结" - -if [ "$DEPLOY_TYPE" = "backend" ] || [ "$DEPLOY_TYPE" = "all" ]; then - if [ "$BACKEND_SUCCESS" = true ]; then - log_info "✅ 后端部署: 成功" - else - log_error "❌ 后端部署: 失败" - fi -fi - -if [ "$DEPLOY_TYPE" = "frontend" ] || [ "$DEPLOY_TYPE" = "all" ]; then - if [ "$FRONTEND_SUCCESS" = true ]; then - log_info "✅ 前端部署: 成功" - else - log_error "❌ 前端部署: 失败" - fi -fi - -if [ "$DEPLOY_TYPE" = "admin" ] || [ "$DEPLOY_TYPE" = "all" ]; then - if [ "$ADMIN_SUCCESS" = true ]; then - log_info "✅ 管理后台部署: 成功" - else - log_error "❌ 管理后台部署: 失败" - fi -fi - -log_info "部署耗时: ${DURATION}秒" - -# ============================================================================ -# 访问信息 -# ============================================================================ - -# 检查部署结果 -ALL_SUCCESS=true -if [ "$DEPLOY_TYPE" = "all" ]; then - if [ "$BACKEND_SUCCESS" = false ] || [ "$FRONTEND_SUCCESS" = false ] || [ "$ADMIN_SUCCESS" = false ]; then - ALL_SUCCESS=false - fi -elif [ "$DEPLOY_TYPE" = "backend" ] && [ "$BACKEND_SUCCESS" = false ]; then - ALL_SUCCESS=false -elif [ "$DEPLOY_TYPE" = "frontend" ] && [ "$FRONTEND_SUCCESS" = false ]; then - ALL_SUCCESS=false -elif [ "$DEPLOY_TYPE" = "admin" ] && [ "$ADMIN_SUCCESS" = false ]; then - ALL_SUCCESS=false -fi - -if [ "$ALL_SUCCESS" = true ]; then - echo "" - log_section "部署成功!" - - if [ "$DEPLOY_TYPE" = "backend" ] || [ "$DEPLOY_TYPE" = "all" ]; then - log_info "🔌 后端API地址: https://lifescript.happylifeos.com/api" - log_info "📊 WebSocket地址: wss://lifescript.happylifeos.com/ws" - fi - - if [ "$DEPLOY_TYPE" = "frontend" ] || [ "$DEPLOY_TYPE" = "all" ]; then - log_info "📱 前端访问地址: https://lifescript.happylifeos.com/" - fi - - if [ "$DEPLOY_TYPE" = "admin" ] || [ "$DEPLOY_TYPE" = "all" ]; then - log_info "🔧 管理后台地址: https://lifescript.happylifeos.com/emotion-museum-admin/" - fi - - echo "" - exit 0 -else - log_error "❌ 部署失败" - exit 1 -fi +# 向后兼容 wrapper - 调用统一的 deploy.sh +# 原 deploy-all.sh 的参数 [backend|frontend|admin|all] 保持不变 +exec bash "$(dirname "$0")/deploy.sh" "$@" diff --git a/deploy-domain.sh b/deploy-domain.sh index 54c4aeb..c3ed7b7 100644 --- a/deploy-domain.sh +++ b/deploy-domain.sh @@ -1,102 +1,4 @@ #!/bin/bash -# -# Author: Emotion Museum Team -# Created: 2026-03-18 -# Purpose: 一键部署域名配置(SSL + Nginx + 后端 + 前端) -# -# 使用方法: -# ./deploy-domain.sh -# -# 前置条件: -# - 已配置 SSH 免密登录到服务器 -# - 服务器已安装 certbot 和 nginx -# - -set -e - -# 配置 -SERVER="101.200.208.45" -DOMAIN="lifescript.happylifeos.com" -EMAIL="admin@happylifeos.com" - -# 颜色 -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' - -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_section() { echo -e "\n${BLUE}==== $1 ====${NC}\n"; } - -log_section "情绪博物馆 - 域名部署" - -# 1. 检查 SSH 连接 -log_info "检查 SSH 连接..." -ssh root@$SERVER "echo 'SSH 连接正常'" || { log_error "SSH 连接失败"; exit 1; } - -# 2. 上传 SSL 证书脚本 -log_info "上传 SSL 证书脚本..." -scp tools/deploy-ssl-cert.py root@$SERVER:/tmp/deploy-ssl-cert.py - -# 3. 执行 SSL 证书验证(证书应该已申请) -log_info "验证 SSL 证书..." -ssh root@$SERVER "python3 /tmp/deploy-ssl-cert.py --verify" || log_warn "证书验证失败,请检查" - -# 4. 上传并应用 Nginx 配置 -log_info "上传 Nginx 配置..." -scp conf/nginx-emotion-museum-fix.conf root@$SERVER:/tmp/nginx-fix.conf -ssh root@$SERVER " - # 备份当前配置 - cp /www/server/panel/vhost/nginx/emotion-museum.conf /www/server/panel/vhost/nginx/emotion-museum.conf.bak 2>/dev/null || true - # 应用新配置 - cp /tmp/nginx-fix.conf /www/server/panel/vhost/nginx/emotion-museum.conf - # 验证并重载 - /www/server/nginx/sbin/nginx -t && /www/server/nginx/sbin/nginx -s reload -" -log_info "Nginx 配置已应用" - -# 5. 部署后端 -log_info "部署后端服务..." -cd backend-single && mvn clean package -DskipTests && cd .. -scp backend-single/target/backend-single-1.0.0.jar root@$SERVER:/opt/emotion-museum/backend.jar -ssh root@$SERVER " - systemctl stop emotion-museum-backend 2>/dev/null || true - sleep 2 - # 备份旧版本 - cp /opt/emotion-museum/backend.jar /opt/emotion-museum/backend.jar.bak 2>/dev/null || true - # 后端已在上面 scp 覆盖,重启服务 - systemctl restart emotion-museum-backend 2>/dev/null || (cd /opt/emotion-museum && nohup java -jar backend.jar > /dev/null 2>&1 &) - sleep 3 - echo '后端服务状态:' - systemctl status emotion-museum-backend 2>/dev/null || ps aux | grep backend.jar | grep -v grep -" - -# 6. 部署前端 -log_info "部署前端..." -cd web && npm run build && cd .. -scp -r web/dist/* root@$SERVER:/data/www/emotion-museum/ -log_info "前端部署完成" - -# 7. 部署管理后台 -log_info "部署管理后台..." -cd web-admin && npm run build && cd .. -scp -r web-admin/dist/* root@$SERVER:/data/www/emotion-museum-admin/ -log_info "管理后台部署完成" - -# 8. 验证部署 -log_section "验证部署" -log_info "验证 HTTPS 访问..." -curl -k -s -o /dev/null -w " 前端页面:HTTP %{http_code}\n" https://$DOMAIN/emotion-museum/ -curl -k -s -o /dev/null -w " 管理后台:HTTP %{http_code}\n" https://$DOMAIN/emotion-museum-admin/ -curl -k -s -o /dev/null -w " API 代理:HTTP %{http_code}\n" https://$DOMAIN/api/health -curl -s -o /dev/null -w " HTTP 跳转:HTTP %{http_code}\n" http://$DOMAIN/ - -log_section "部署完成" -log_info "访问地址:" -log_info " 用户前端:https://$DOMAIN/emotion-museum/" -log_info " 管理后台:https://$DOMAIN/emotion-museum-admin/" -log_info " API 地址:https://$DOMAIN/api/" -log_info " WebSocket: wss://$DOMAIN/ws" +# 向后兼容 wrapper - 调用统一的 deploy.sh +# 原 deploy-domain.sh 为无参数全量部署,等价于 deploy.sh all +exec bash "$(dirname "$0")/deploy.sh" all diff --git a/deploy-to-prod.sh b/deploy-to-prod.sh index 06c119e..dd65fb3 100644 --- a/deploy-to-prod.sh +++ b/deploy-to-prod.sh @@ -1,252 +1,4 @@ #!/bin/bash -# Author: huazhongmin -# Created: 2026-03-17 -# Purpose: 域名一键部署脚本 - 支持 SSL 证书申请、前端、后端、nginx 配置部署 - -# 情绪博物馆 - 域名部署脚本 -# 域名:lifescript.happylifeos.com -# 使用方法:bash deploy-to-prod.sh [ssl|frontend|admin|life-script|backend|nginx|all] - -set -e - -# 颜色定义 -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' - -# 日志函数 -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_section() { - echo "" - echo -e "${BLUE}╔════════════════════════════════════════════════════════════════╗${NC}" - echo -e "${BLUE}║${NC} $1" - echo -e "${BLUE}╚════════════════════════════════════════════════════════════════╝${NC}" - echo "" -} - -# 服务器配置 -SERVER_IP="101.200.208.45" -USERNAME="root" -DOMAIN="lifescript.happylifeos.com" - -# SSL 证书申请 -deploy_ssl() { - log_section "申请 SSL 证书" - - if [ ! -f "tools/deploy-ssl-cert.py" ]; then - log_error "SSL 证书脚本不存在:tools/deploy-ssl-cert.py" - return 1 - fi - - log_info "在服务器上执行 SSL 证书申请..." - scp tools/deploy-ssl-cert.py ${USERNAME}@${SERVER_IP}:/tmp/deploy-ssl-cert.py - ssh ${USERNAME}@${SERVER_IP} "python3 /tmp/deploy-ssl-cert.py" - - if [ $? -eq 0 ]; then - log_info "✅ SSL 证书申请完成" - return 0 - else - log_error "❌ SSL 证书申请失败" - return 1 - fi -} - -# 部署后端 -deploy_backend() { - log_section "部署后端服务" - - if [ ! -f "backend-single/deploy.sh" ]; then - log_error "后端部署脚本不存在" - return 1 - fi - - log_info "执行后端部署..." - cd backend-single - bash deploy.sh remote - local result=$? - cd .. - - if [ $result -eq 0 ]; then - log_info "✅ 后端部署完成" - return 0 - else - log_error "❌ 后端部署失败" - return 1 - fi -} - -# 部署前端 -deploy_frontend() { - log_section "部署用户前端" - - if [ ! -f "web/deploy.sh" ]; then - log_error "前端部署脚本不存在" - return 1 - fi - - log_info "执行前端部署..." - cd web - bash deploy.sh - local result=$? - cd .. - - if [ $result -eq 0 ]; then - log_info "✅ 前端部署完成" - return 0 - else - log_error "❌ 前端部署失败" - return 1 - fi -} - -# 部署管理后台 -deploy_admin() { - log_section "部署管理后台" - - if [ ! -f "web-admin/deploy.sh" ]; then - log_error "管理后台部署脚本不存在" - return 1 - fi - - log_info "执行管理后台部署..." - cd web-admin - bash deploy.sh - local result=$? - cd .. - - if [ $result -eq 0 ]; then - log_info "✅ 管理后台部署完成" - return 0 - else - log_error "❌ 管理后台部署失败" - return 1 - fi -} - -# 部署 Life-Script -deploy_life_script() { - log_section "部署 Life-Script" - - if [ ! -f "life-script/deploy.sh" ]; then - log_error "Life-Script 部署脚本不存在" - return 1 - fi - - log_info "执行 Life-Script 部署..." - cd life-script - bash deploy.sh - local result=$? - cd .. - - if [ $result -eq 0 ]; then - log_info "✅ Life-Script 部署完成" - return 0 - else - log_error "❌ Life-Script 部署失败" - return 1 - fi -} - -# 部署 Nginx 配置 -deploy_nginx() { - log_section "部署 Nginx 配置" - - if [ ! -f "conf/emotion-museum.conf" ]; then - log_error "Nginx 配置文件不存在" - return 1 - fi - - log_info "上传 Nginx 配置文件..." - scp conf/emotion-museum.conf ${USERNAME}@${SERVER_IP}:/etc/nginx/sites-available/${DOMAIN}.conf - - log_info "启用站点配置..." - ssh ${USERNAME}@${SERVER_IP} "ln -snf /etc/nginx/sites-available/${DOMAIN}.conf /etc/nginx/sites-enabled/${DOMAIN}.conf" - - log_info "移除默认配置(如果存在冲突)..." - ssh ${USERNAME}@${SERVER_IP} "rm -f /etc/nginx/sites-enabled/default" - - log_info "验证 Nginx 配置..." - if ssh ${USERNAME}@${SERVER_IP} "nginx -t"; then - log_info "Nginx 配置验证通过" - ssh ${USERNAME}@${SERVER_IP} "systemctl reload nginx" - log_info "✅ Nginx 配置重载完成" - return 0 - else - log_error "❌ Nginx 配置验证失败" - return 1 - fi -} - -# 主程序 -main() { - DEPLOY_TYPE="${1:-all}" - - log_section "情绪博物馆 - 域名部署" - log_info "域名:https://${DOMAIN}" - log_info "部署类型:${DEPLOY_TYPE}" - log_info "部署时间:$(date '+%Y-%m-%d %H:%M:%S')" - - case "$DEPLOY_TYPE" in - ssl) - deploy_ssl - ;; - backend) - deploy_backend - ;; - frontend) - deploy_frontend - ;; - admin) - deploy_admin - ;; - life-script) - deploy_life_script - ;; - nginx) - deploy_nginx - ;; - all) - deploy_ssl - deploy_nginx - deploy_backend - deploy_frontend - deploy_admin - deploy_life_script - ;; - *) - log_error "无效的部署类型:$DEPLOY_TYPE" - echo "使用方法:bash deploy-to-prod.sh [ssl|backend|frontend|admin|life-script|nginx|all]" - exit 1 - ;; - esac - - log_section "部署完成" - - if [ "$DEPLOY_TYPE" = "all" ] || [ "$DEPLOY_TYPE" = "ssl" ]; then - log_info "📋 验证 SSL 证书:运行 python3 tools/deploy-ssl-cert.py --verify" - fi - - if [ "$DEPLOY_TYPE" = "all" ] || [ "$DEPLOY_TYPE" = "nginx" ]; then - log_info "🌐 访问地址:" - log_info " 用户前端:https://${DOMAIN}/" - log_info " 管理后台:https://${DOMAIN}/emotion-museum-admin/" - log_info " Life-Script: https://${DOMAIN}/life-script/" - log_info " API 地址:https://${DOMAIN}/api" - log_info " WebSocket: wss://${DOMAIN}/ws" - fi -} - -main "$@" +# 向后兼容 wrapper - 调用统一的 deploy.sh +# 原 deploy-to-prod.sh 的参数 [ssl|backend|frontend|admin|life-script|nginx|all] 保持不变 +exec bash "$(dirname "$0")/deploy.sh" "$@" diff --git a/deploy.sh b/deploy.sh new file mode 100644 index 0000000..1edcbce --- /dev/null +++ b/deploy.sh @@ -0,0 +1,258 @@ +#!/bin/bash +# Author: emotion-museum team +# Created: 2026-05-12 +# Purpose: 统一部署脚本 - 合并 deploy-all.sh / deploy-to-prod.sh / deploy-domain.sh +# +# 使用方法: +# bash deploy.sh # 部署所有服务 +# bash deploy.sh backend # 仅部署后端 +# bash deploy.sh frontend # 仅部署前端 +# bash deploy.sh admin # 仅部署管理后台 +# bash deploy.sh life-script # 仅部署 Life-Script +# bash deploy.sh ssl # 仅申请 SSL 证书 +# bash deploy.sh nginx # 仅部署 Nginx 配置 +# bash deploy.sh verify # 仅验证部署结果 +# bash deploy.sh all # 部署所有服务(同无参数) + +set -e + +# ============================================================================ +# 配置 +# ============================================================================ +SERVER_IP="101.200.208.45" +USERNAME="root" +DOMAIN="lifescript.happylifeos.com" + +# ============================================================================ +# 日志 +# ============================================================================ +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +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_section() { echo -e "\n${BLUE}╔═══════════════════════════════════════════════════════════╗${NC}"; echo -e "${BLUE}║${NC} $1"; echo -e "${BLUE}╚═══════════════════════════════════════════════════════════╝${NC}\n"; } + +# ============================================================================ +# 工具函数 +# ============================================================================ +check_ssh() { + log_info "检查 SSH 连接..." + if ssh -o BatchMode=yes -o ConnectTimeout=10 ${USERNAME}@${SERVER_IP} "echo ok" > /dev/null 2>&1; then + log_info "SSH 连接正常" + else + log_error "SSH 连接失败,请先配置免密登录: ssh ${USERNAME}@${SERVER_IP}" + exit 1 + fi +} + +# ============================================================================ +# SSL 证书 +# ============================================================================ +deploy_ssl() { + log_section "申请 SSL 证书" + if [ ! -f "tools/deploy-ssl-cert.py" ]; then + log_error "SSL 证书脚本不存在: tools/deploy-ssl-cert.py" + return 1 + fi + log_info "上传并执行 SSL 证书脚本..." + scp tools/deploy-ssl-cert.py ${USERNAME}@${SERVER_IP}:/tmp/deploy-ssl-cert.py + ssh ${USERNAME}@${SERVER_IP} "python3 /tmp/deploy-ssl-cert.py" + log_info "✅ SSL 证书申请完成" +} + +# ============================================================================ +# Nginx 配置 +# ============================================================================ +deploy_nginx() { + log_section "部署 Nginx 配置" + if [ ! -f "conf/emotion-museum.conf" ]; then + log_error "Nginx 配置文件不存在: conf/emotion-museum.conf" + return 1 + fi + log_info "上传 Nginx 配置文件..." + scp conf/emotion-museum.conf ${USERNAME}@${SERVER_IP}:/etc/nginx/sites-available/${DOMAIN}.conf + log_info "启用站点配置..." + ssh ${USERNAME}@${SERVER_IP} "ln -snf /etc/nginx/sites-available/${DOMAIN}.conf /etc/nginx/sites-enabled/${DOMAIN}.conf && rm -f /etc/nginx/sites-enabled/default" + log_info "验证 Nginx 配置..." + if ssh ${USERNAME}@${SERVER_IP} "nginx -t"; then + ssh ${USERNAME}@${SERVER_IP} "systemctl reload nginx" + log_info "✅ Nginx 配置重载完成" + else + log_error "❌ Nginx 配置验证失败" + return 1 + fi +} + +# ============================================================================ +# 后端 - 调用 backend-single/deploy.sh +# ============================================================================ +deploy_backend() { + log_section "部署后端服务" + if [ ! -f "backend-single/deploy.sh" ]; then + log_error "后端部署脚本不存在: backend-single/deploy.sh" + return 1 + fi + log_info "执行后端部署..." + cd backend-single + if bash deploy.sh remote; then + cd .. + log_info "✅ 后端部署完成" + return 0 + else + cd .. + log_error "❌ 后端部署失败" + return 1 + fi +} + +# ============================================================================ +# 前端 - 调用 web/deploy.sh +# ============================================================================ +deploy_frontend() { + log_section "部署用户前端" + if [ ! -f "web/deploy.sh" ]; then + log_error "前端部署脚本不存在: web/deploy.sh" + return 1 + fi + log_info "执行前端部署..." + cd web + if bash deploy.sh; then + cd .. + log_info "✅ 前端部署完成" + return 0 + else + cd .. + log_error "❌ 前端部署失败" + return 1 + fi +} + +# ============================================================================ +# 管理后台 - 调用 web-admin/deploy.py +# ============================================================================ +deploy_admin() { + log_section "部署管理后台" + if [ ! -f "web-admin/deploy.py" ]; then + log_error "管理后台部署脚本不存在: web-admin/deploy.py" + return 1 + fi + log_info "执行管理后台部署..." + cd web-admin + if python3 deploy.py; then + cd .. + log_info "✅ 管理后台部署完成" + return 0 + else + cd .. + log_error "❌ 管理后台部署失败" + return 1 + fi +} + +# ============================================================================ +# Life-Script - 调用 life-script/deploy.sh +# ============================================================================ +deploy_life_script() { + log_section "部署 Life-Script" + if [ ! -f "life-script/deploy.sh" ]; then + log_error "Life-Script 部署脚本不存在: life-script/deploy.sh" + return 1 + fi + log_info "执行 Life-Script 部署..." + cd life-script + if bash deploy.sh; then + cd .. + log_info "✅ Life-Script 部署完成" + return 0 + else + cd .. + log_error "❌ Life-Script 部署失败" + return 1 + fi +} + +# ============================================================================ +# 验证部署 +# ============================================================================ +verify_deploy() { + log_section "验证部署" + log_info "检查 HTTPS 访问..." + curl -k -s -o /dev/null -w " 前端页面: HTTP %{http_code}\n" https://${DOMAIN}/ || log_warn "前端访问异常" + curl -k -s -o /dev/null -w " 管理后台: HTTP %{http_code}\n" https://${DOMAIN}/emotion-museum-admin/ || log_warn "管理后台访问异常" + curl -k -s -o /dev/null -w " API 代理: HTTP %{http_code}\n" https://${DOMAIN}/api/ || log_warn "API 访问异常" + curl -k -s -o /dev/null -w " HTTP 跳转: HTTP %{http_code}\n" http://${DOMAIN}/ || log_warn "HTTP 跳转异常" + log_info "✅ 验证完成" +} + +# ============================================================================ +# 主程序 +# ============================================================================ +main() { + DEPLOY_TYPE="${1:-all}" + START_TIME=$(date +%s) + + log_section "情绪博物馆 - 统一部署" + log_info "部署类型: ${DEPLOY_TYPE}" + log_info "部署时间: $(date '+%Y-%m-%d %H:%M:%S')" + + case "$DEPLOY_TYPE" in + ssl) + check_ssh + deploy_ssl + ;; + backend) + check_ssh + deploy_backend + ;; + frontend) + check_ssh + deploy_frontend + ;; + admin) + check_ssh + deploy_admin + ;; + life-script) + check_ssh + deploy_life_script + ;; + nginx) + check_ssh + deploy_nginx + ;; + verify) + verify_deploy + ;; + all) + check_ssh + deploy_ssl || true + deploy_nginx || true + deploy_backend + deploy_frontend + deploy_admin + deploy_life_script + verify_deploy + ;; + *) + log_error "无效的部署类型: $DEPLOY_TYPE" + echo "使用方法: bash deploy.sh [ssl|backend|frontend|admin|life-script|nginx|verify|all]" + exit 1 + ;; + esac + + END_TIME=$(date +%s) + DURATION=$((END_TIME - START_TIME)) + log_section "部署完成 (耗时 ${DURATION}s)" + log_info "用户前端: https://${DOMAIN}/" + log_info "管理后台: https://${DOMAIN}/emotion-museum-admin/" + log_info "Life-Script: https://${DOMAIN}/life-script/" + log_info "API 地址: https://${DOMAIN}/api" + log_info "WebSocket: wss://${DOMAIN}/ws" +} + +main "$@"