b150cede84
✨ 新增功能: - 全量部署脚本 (backend/deploy-all.sh) - 支持一键部署所有微服务 - 单服务部署脚本 - 每个微服务独立部署脚本 - 前端部署脚本 (web-flowith/deploy.sh) - Vue应用自动构建部署 - Jenkins CI/CD 支持 - 完整的Pipeline配置 �� 部署特性: - 容错机制: 单个服务失败不影响其他服务部署 - 详细报告: 完整的部署状态统计和错误日志 - 容器化: 使用Docker进行服务部署 - 健康检查: 自动验证服务启动状态 - 版本备份: 自动备份旧版本支持快速回滚 🛠️ 技术改进: - emotion-auth服务启动问题修复 - 跨域配置优化 - 数据库连接配置统一 - OAuth服务实现完善 - WebSocket依赖更新 📚 文档: - Jenkins部署说明文档 - 部署脚本使用指南 - 故障排查手册 🌐 部署环境: - 目标服务器: 47.111.10.27 - 容器化部署到 /data/builds - 前端部署到 /data/www/emotion-museum - 支持test/prod环境配置
345 lines
8.7 KiB
Bash
Executable File
345 lines
8.7 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# 情感博物馆前端部署脚本
|
|
# 作者: emotion-museum
|
|
# 日期: 2025-07-18
|
|
# 支持Jenkins CI/CD部署
|
|
|
|
set -e
|
|
|
|
# 配置变量 - 支持Jenkins环境变量覆盖
|
|
REMOTE_HOST="${DEPLOY_HOST:-root@47.111.10.27}"
|
|
REMOTE_WEB_DIR="${REMOTE_WEB_DIR:-/data/www/emotion-museum}"
|
|
FRONTEND_DIR="web-flowith"
|
|
PROJECT_NAME="emotion-museum-frontend"
|
|
|
|
# Jenkins构建信息
|
|
BUILD_NUMBER="${BUILD_NUMBER:-manual}"
|
|
JOB_NAME="${JOB_NAME:-local-deploy}"
|
|
BUILD_URL="${BUILD_URL:-}"
|
|
|
|
# 颜色输出
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
# 日志函数
|
|
log_info() {
|
|
echo -e "${BLUE}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
|
|
}
|
|
|
|
log_success() {
|
|
echo -e "${GREEN}[SUCCESS]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
|
|
}
|
|
|
|
log_warning() {
|
|
echo -e "${YELLOW}[WARNING]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
|
|
}
|
|
|
|
log_error() {
|
|
echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
|
|
}
|
|
|
|
# 检查远程服务器连接
|
|
check_remote_connection() {
|
|
log_info "检查远程服务器连接..."
|
|
if ssh -o ConnectTimeout=10 $REMOTE_HOST "echo 'Connection successful'" > /dev/null 2>&1; then
|
|
log_success "远程服务器连接正常"
|
|
return 0
|
|
else
|
|
log_error "无法连接到远程服务器 $REMOTE_HOST"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# 检查本地环境
|
|
check_local_environment() {
|
|
log_info "检查本地构建环境..."
|
|
|
|
# 检查Node.js
|
|
if ! command -v node &> /dev/null; then
|
|
log_error "Node.js 未安装"
|
|
return 1
|
|
fi
|
|
|
|
# 检查npm
|
|
if ! command -v npm &> /dev/null; then
|
|
log_error "npm 未安装"
|
|
return 1
|
|
fi
|
|
|
|
log_info "Node.js 版本: $(node --version)"
|
|
log_info "npm 版本: $(npm --version)"
|
|
log_success "本地环境检查通过"
|
|
return 0
|
|
}
|
|
|
|
# 安装依赖
|
|
install_dependencies() {
|
|
log_info "安装前端依赖..."
|
|
|
|
if [ -f "package-lock.json" ]; then
|
|
npm ci --silent
|
|
else
|
|
npm install --silent
|
|
fi
|
|
|
|
log_success "依赖安装完成"
|
|
}
|
|
|
|
# 构建前端项目
|
|
build_frontend() {
|
|
log_info "构建前端项目..."
|
|
|
|
# 设置生产环境变量
|
|
export NODE_ENV=production
|
|
export VITE_API_BASE_URL=http://47.111.10.27:19000
|
|
|
|
# 执行构建
|
|
if npm run build; then
|
|
log_success "前端项目构建成功"
|
|
|
|
# 检查构建产物
|
|
if [ -d "dist" ]; then
|
|
local dist_size=$(du -sh dist | cut -f1)
|
|
log_info "构建产物大小: $dist_size"
|
|
log_info "构建产物文件:"
|
|
ls -la dist/ | head -10
|
|
else
|
|
log_error "构建产物目录不存在"
|
|
return 1
|
|
fi
|
|
else
|
|
log_error "前端项目构建失败"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# 创建远程目录
|
|
create_remote_directories() {
|
|
log_info "创建远程目录结构..."
|
|
ssh $REMOTE_HOST "
|
|
mkdir -p $REMOTE_WEB_DIR
|
|
mkdir -p $REMOTE_WEB_DIR/backup
|
|
mkdir -p /data/logs/nginx
|
|
"
|
|
log_success "远程目录创建完成"
|
|
}
|
|
|
|
# 备份旧版本
|
|
backup_old_version() {
|
|
log_info "备份旧版本..."
|
|
|
|
local backup_name="backup_$(date +%Y%m%d_%H%M%S)"
|
|
|
|
ssh $REMOTE_HOST "
|
|
if [ -d '$REMOTE_WEB_DIR/$FRONTEND_DIR' ]; then
|
|
mv '$REMOTE_WEB_DIR/$FRONTEND_DIR' '$REMOTE_WEB_DIR/backup/$backup_name'
|
|
echo '旧版本已备份到: $REMOTE_WEB_DIR/backup/$backup_name'
|
|
|
|
# 只保留最近5个备份
|
|
cd '$REMOTE_WEB_DIR/backup'
|
|
ls -t | tail -n +6 | xargs -r rm -rf
|
|
else
|
|
echo '没有发现旧版本,跳过备份'
|
|
fi
|
|
"
|
|
|
|
log_success "备份完成"
|
|
}
|
|
|
|
# 部署前端文件
|
|
deploy_frontend() {
|
|
log_info "部署前端文件到远程服务器..."
|
|
|
|
# 上传构建产物
|
|
if scp -r dist/ "$REMOTE_HOST:$REMOTE_WEB_DIR/$FRONTEND_DIR/"; then
|
|
log_success "前端文件上传成功"
|
|
else
|
|
log_error "前端文件上传失败"
|
|
return 1
|
|
fi
|
|
|
|
# 设置文件权限
|
|
ssh $REMOTE_HOST "
|
|
chown -R www-data:www-data '$REMOTE_WEB_DIR/$FRONTEND_DIR' 2>/dev/null || true
|
|
chmod -R 755 '$REMOTE_WEB_DIR/$FRONTEND_DIR'
|
|
"
|
|
|
|
log_success "文件权限设置完成"
|
|
}
|
|
|
|
# 配置Nginx
|
|
configure_nginx() {
|
|
log_info "配置Nginx..."
|
|
|
|
# 创建Nginx配置
|
|
ssh $REMOTE_HOST "cat > /etc/nginx/sites-available/emotion-museum << 'EOF'
|
|
server {
|
|
listen 80;
|
|
server_name 47.111.10.27;
|
|
|
|
# 前端静态文件
|
|
location /emotion-museum {
|
|
alias $REMOTE_WEB_DIR/$FRONTEND_DIR;
|
|
index index.html;
|
|
try_files \$uri \$uri/ /emotion-museum/index.html;
|
|
|
|
# 静态资源缓存
|
|
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
|
expires 1y;
|
|
add_header Cache-Control \"public, immutable\";
|
|
}
|
|
|
|
# HTML文件不缓存
|
|
location ~* \.html$ {
|
|
expires -1;
|
|
add_header Cache-Control \"no-cache, no-store, must-revalidate\";
|
|
}
|
|
}
|
|
|
|
# API代理到后端网关
|
|
location /api/ {
|
|
proxy_pass http://127.0.0.1:19000/;
|
|
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;
|
|
|
|
# WebSocket支持
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Upgrade \$http_upgrade;
|
|
proxy_set_header Connection \"upgrade\";
|
|
}
|
|
|
|
# 日志配置
|
|
access_log /data/logs/nginx/emotion-museum-access.log;
|
|
error_log /data/logs/nginx/emotion-museum-error.log;
|
|
}
|
|
EOF"
|
|
|
|
# 启用站点
|
|
ssh $REMOTE_HOST "
|
|
ln -sf /etc/nginx/sites-available/emotion-museum /etc/nginx/sites-enabled/
|
|
nginx -t && systemctl reload nginx
|
|
" 2>/dev/null || log_warning "Nginx配置可能需要手动检查"
|
|
|
|
log_success "Nginx配置完成"
|
|
}
|
|
|
|
# 健康检查
|
|
health_check() {
|
|
log_info "执行健康检查..."
|
|
|
|
sleep 3
|
|
|
|
# 检查前端页面
|
|
if curl -f -s "http://47.111.10.27/emotion-museum/" > /dev/null 2>&1; then
|
|
log_success "前端页面访问正常"
|
|
else
|
|
log_warning "前端页面访问异常,请检查Nginx配置"
|
|
fi
|
|
|
|
# 检查API代理
|
|
if curl -f -s "http://47.111.10.27/api/user/health" > /dev/null 2>&1; then
|
|
log_success "API代理正常"
|
|
else
|
|
log_warning "API代理异常,请检查后端服务状态"
|
|
fi
|
|
}
|
|
|
|
# 显示部署报告
|
|
show_deployment_report() {
|
|
local total_time=$1
|
|
|
|
echo ""
|
|
echo "========================================"
|
|
echo " 前端部署完成报告"
|
|
echo "========================================"
|
|
echo "项目名称: $PROJECT_NAME"
|
|
echo "目标服务器: $REMOTE_HOST"
|
|
echo "部署路径: $REMOTE_WEB_DIR/$FRONTEND_DIR"
|
|
echo "部署时间: $(date '+%Y-%m-%d %H:%M:%S')"
|
|
echo "总耗时: ${total_time}s"
|
|
if [ "$BUILD_NUMBER" != "manual" ]; then
|
|
echo "Jenkins构建: #$BUILD_NUMBER"
|
|
echo "Jenkins任务: $JOB_NAME"
|
|
[ -n "$BUILD_URL" ] && echo "构建链接: $BUILD_URL"
|
|
fi
|
|
echo "========================================"
|
|
|
|
echo ""
|
|
echo "🌐 访问地址:"
|
|
echo " 前端页面: http://47.111.10.27/emotion-museum/"
|
|
echo " API接口: http://47.111.10.27/api/"
|
|
|
|
echo ""
|
|
echo "📁 远程文件信息:"
|
|
ssh $REMOTE_HOST "
|
|
echo '部署目录大小:'
|
|
du -sh '$REMOTE_WEB_DIR/$FRONTEND_DIR' 2>/dev/null || echo '无法获取目录大小'
|
|
echo ''
|
|
echo '主要文件:'
|
|
ls -la '$REMOTE_WEB_DIR/$FRONTEND_DIR' 2>/dev/null | head -10 || echo '无法列出文件'
|
|
"
|
|
|
|
echo ""
|
|
echo "========================================"
|
|
echo "🎉 前端部署完成!"
|
|
}
|
|
|
|
# 主函数
|
|
main() {
|
|
local start_time=$(date +%s)
|
|
|
|
log_info "🚀 开始前端部署..."
|
|
log_info "目标服务器: $REMOTE_HOST"
|
|
log_info "部署路径: $REMOTE_WEB_DIR/$FRONTEND_DIR"
|
|
|
|
# 检查环境
|
|
if ! check_local_environment; then
|
|
log_error "本地环境检查失败"
|
|
exit 1
|
|
fi
|
|
|
|
if ! check_remote_connection; then
|
|
log_error "远程服务器连接失败"
|
|
exit 1
|
|
fi
|
|
|
|
# 安装依赖
|
|
install_dependencies
|
|
|
|
# 构建项目
|
|
build_frontend
|
|
|
|
# 创建远程目录
|
|
create_remote_directories
|
|
|
|
# 备份旧版本
|
|
backup_old_version
|
|
|
|
# 部署文件
|
|
deploy_frontend
|
|
|
|
# 配置Nginx
|
|
configure_nginx
|
|
|
|
# 健康检查
|
|
health_check
|
|
|
|
# 计算总耗时
|
|
local end_time=$(date +%s)
|
|
local total_time=$((end_time - start_time))
|
|
|
|
# 显示报告
|
|
show_deployment_report $total_time
|
|
|
|
log_success "🎉 前端部署完成!"
|
|
}
|
|
|
|
# 执行主函数
|
|
main "$@"
|