1202 lines
33 KiB
Bash
Executable File
1202 lines
33 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# ===================================================================
|
|
# 情绪博物馆项目 - 最终版本一键部署脚本
|
|
# 支持完整部署、增量更新、服务管理等功能
|
|
# 作者: Emotion Museum Team
|
|
# 版本: 1.0.0
|
|
# 日期: 2025-07-13
|
|
# ===================================================================
|
|
|
|
set -e # 遇到错误立即退出
|
|
|
|
# ===================================================================
|
|
# 全局配置
|
|
# ===================================================================
|
|
|
|
# 服务器配置
|
|
readonly SERVER_HOST="47.111.10.27"
|
|
readonly SERVER_USER="root"
|
|
readonly SERVER_IP="47.111.10.27"
|
|
|
|
# 目录配置
|
|
readonly REMOTE_BASE_DIR="/data"
|
|
readonly REMOTE_BUILDS_DIR="${REMOTE_BASE_DIR}/builds"
|
|
readonly REMOTE_WEB_DIR="${REMOTE_BASE_DIR}/www/emotion-museum/web"
|
|
readonly REMOTE_LOGS_DIR="${REMOTE_BASE_DIR}/logs/emotion-museum"
|
|
readonly REMOTE_PROGRAMS_DIR="${REMOTE_BASE_DIR}/programs"
|
|
|
|
# 数据库配置
|
|
readonly MYSQL_HOST="localhost"
|
|
readonly MYSQL_PORT="3306"
|
|
readonly MYSQL_DATABASE="emotion_museum"
|
|
readonly MYSQL_USERNAME="emotion"
|
|
readonly MYSQL_PASSWORD="EmotionDB2024!"
|
|
readonly MYSQL_ROOT_PASSWORD="123456"
|
|
|
|
# 服务配置
|
|
readonly NACOS_SERVER_ADDR="localhost:8848"
|
|
readonly REDIS_HOST="localhost"
|
|
readonly REDIS_PORT="6379"
|
|
readonly COZE_API_TOKEN="pat_GCR4qKzqpf90wMCvKsldMrB18KG3QsLDci65bZthssKsbLxu8X70BKYumleDcabO"
|
|
|
|
# 应用配置
|
|
readonly APP_VERSION="1.0.0"
|
|
readonly SPRING_PROFILES_ACTIVE="prod"
|
|
|
|
# 颜色定义
|
|
readonly RED='\033[0;31m'
|
|
readonly GREEN='\033[0;32m'
|
|
readonly YELLOW='\033[1;33m'
|
|
readonly BLUE='\033[0;34m'
|
|
readonly PURPLE='\033[0;35m'
|
|
readonly CYAN='\033[0;36m'
|
|
readonly WHITE='\033[1;37m'
|
|
readonly NC='\033[0m' # No Color
|
|
|
|
# ===================================================================
|
|
# 工具函数
|
|
# ===================================================================
|
|
|
|
# 日志函数
|
|
log_info() {
|
|
echo -e "${BLUE}[INFO]${NC} $1"
|
|
}
|
|
|
|
log_success() {
|
|
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
|
}
|
|
|
|
log_warn() {
|
|
echo -e "${YELLOW}[WARN]${NC} $1"
|
|
}
|
|
|
|
log_error() {
|
|
echo -e "${RED}[ERROR]${NC} $1"
|
|
}
|
|
|
|
log_step() {
|
|
echo -e "${PURPLE}[STEP]${NC} $1"
|
|
}
|
|
|
|
# 进度显示
|
|
show_progress() {
|
|
local current=$1
|
|
local total=$2
|
|
local desc=$3
|
|
local percent=$((current * 100 / total))
|
|
local bar_length=50
|
|
local filled_length=$((percent * bar_length / 100))
|
|
|
|
printf "\r${CYAN}[%3d%%]${NC} [" "$percent"
|
|
printf "%*s" "$filled_length" | tr ' ' '='
|
|
printf "%*s" $((bar_length - filled_length)) | tr ' ' '-'
|
|
printf "] %s" "$desc"
|
|
|
|
if [ "$current" -eq "$total" ]; then
|
|
echo ""
|
|
fi
|
|
}
|
|
|
|
# 检查命令是否存在
|
|
check_command() {
|
|
if ! command -v "$1" &> /dev/null; then
|
|
log_error "命令 '$1' 未找到,请先安装"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# 远程执行命令
|
|
remote_exec() {
|
|
ssh -o StrictHostKeyChecking=no "${SERVER_USER}@${SERVER_HOST}" "$1"
|
|
}
|
|
|
|
# 检查服务器连接
|
|
check_server_connection() {
|
|
log_step "检查服务器连接..."
|
|
if ! ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=no "${SERVER_USER}@${SERVER_HOST}" "echo 'Connection OK'" &>/dev/null; then
|
|
log_error "无法连接到服务器 ${SERVER_HOST}"
|
|
log_info "请检查:"
|
|
log_info "1. 服务器IP地址是否正确"
|
|
log_info "2. SSH密钥是否配置正确"
|
|
log_info "3. 网络连接是否正常"
|
|
exit 1
|
|
fi
|
|
|
|
log_success "服务器连接正常"
|
|
|
|
# 显示服务器信息
|
|
log_info "服务器信息:"
|
|
remote_exec "
|
|
echo ' 内核版本:' \$(uname -r)
|
|
echo ' 当前用户:' \$(whoami)
|
|
echo ' 当前时间:' \$(date)
|
|
"
|
|
}
|
|
|
|
# 检查本地环境
|
|
check_local_environment() {
|
|
log_step "检查本地环境..."
|
|
|
|
# 检查必要的命令
|
|
check_command "ssh"
|
|
check_command "scp"
|
|
check_command "java"
|
|
check_command "mvn"
|
|
check_command "npm"
|
|
|
|
# 检查Java版本
|
|
local java_version=$(java -version 2>&1 | head -n 1 | cut -d'"' -f2 | cut -d'.' -f1)
|
|
if [ "$java_version" -lt 17 ]; then
|
|
log_error "需要Java 17或更高版本,当前版本: $java_version"
|
|
exit 1
|
|
fi
|
|
|
|
log_success "本地环境检查通过"
|
|
}
|
|
|
|
# ===================================================================
|
|
# 构建函数
|
|
# ===================================================================
|
|
|
|
# 构建后端服务
|
|
build_backend() {
|
|
log_step "构建后端服务..."
|
|
|
|
if [ ! -f "backend/pom.xml" ]; then
|
|
log_error "未找到backend/pom.xml文件,请在项目根目录执行"
|
|
exit 1
|
|
fi
|
|
|
|
# 进入backend目录
|
|
cd backend
|
|
|
|
# 清理并构建
|
|
log_info "执行Maven构建..."
|
|
mvn clean package -DskipTests -Pprod
|
|
|
|
# 返回项目根目录
|
|
cd ..
|
|
|
|
# 检查构建结果
|
|
local services=("emotion-gateway" "emotion-ai" "emotion-user")
|
|
for service in "${services[@]}"; do
|
|
local jar_file="backend/${service}/target/${service}-${APP_VERSION}.jar"
|
|
if [ ! -f "$jar_file" ]; then
|
|
log_error "构建失败: $jar_file 不存在"
|
|
exit 1
|
|
fi
|
|
log_success "✅ ${service} 构建成功"
|
|
done
|
|
|
|
log_success "后端服务构建完成"
|
|
}
|
|
|
|
# 构建前端应用
|
|
build_frontend() {
|
|
log_step "构建前端应用..."
|
|
|
|
cd web
|
|
|
|
# 安装依赖
|
|
if [ ! -d "node_modules" ]; then
|
|
log_info "安装前端依赖..."
|
|
npm install
|
|
fi
|
|
|
|
# 构建生产版本
|
|
log_info "构建生产版本..."
|
|
npm run build
|
|
|
|
# 检查构建结果
|
|
if [ ! -d "dist" ]; then
|
|
log_error "前端构建失败: dist目录不存在"
|
|
exit 1
|
|
fi
|
|
|
|
cd ..
|
|
log_success "前端应用构建完成"
|
|
}
|
|
|
|
# ===================================================================
|
|
# 服务器环境配置
|
|
# ===================================================================
|
|
|
|
# 创建目录结构
|
|
setup_directories() {
|
|
log_step "创建目录结构..."
|
|
|
|
remote_exec "
|
|
# 创建主要目录
|
|
mkdir -p ${REMOTE_BASE_DIR}/{builds,www/emotion-museum,logs/emotion-museum,programs}
|
|
mkdir -p ${REMOTE_LOGS_DIR}/{gateway,ai,user,nacos}
|
|
|
|
# 设置权限
|
|
chmod -R 755 ${REMOTE_BASE_DIR}
|
|
|
|
echo '目录结构创建完成'
|
|
"
|
|
|
|
log_success "目录结构创建完成"
|
|
}
|
|
|
|
# 安装基础软件包
|
|
install_basic_packages() {
|
|
log_step "安装基础软件包..."
|
|
|
|
remote_exec "
|
|
# 更新系统
|
|
yum update -y
|
|
|
|
# 安装基础工具
|
|
yum install -y wget curl vim git unzip lsof net-tools
|
|
|
|
# 安装开发工具
|
|
yum groupinstall -y 'Development Tools'
|
|
|
|
echo '基础软件包安装完成'
|
|
"
|
|
|
|
log_success "基础软件包安装完成"
|
|
}
|
|
|
|
# 安装Docker
|
|
install_docker() {
|
|
log_step "安装Docker..."
|
|
|
|
remote_exec "
|
|
# 检查Docker是否已安装
|
|
if command -v docker &> /dev/null; then
|
|
echo 'Docker已安装,跳过安装步骤'
|
|
exit 0
|
|
fi
|
|
|
|
# 安装Docker
|
|
yum install -y yum-utils
|
|
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
|
|
yum install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
|
|
|
|
# 启动Docker服务
|
|
systemctl start docker
|
|
systemctl enable docker
|
|
|
|
# 验证安装
|
|
docker --version
|
|
|
|
echo 'Docker安装完成'
|
|
"
|
|
|
|
log_success "Docker安装完成"
|
|
}
|
|
|
|
# 安装Java 17
|
|
install_java() {
|
|
log_step "安装Java 17..."
|
|
|
|
remote_exec "
|
|
# 检查Java是否已安装
|
|
if java -version 2>&1 | grep -q '17\\.'; then
|
|
echo 'Java 17已安装,跳过安装步骤'
|
|
exit 0
|
|
fi
|
|
|
|
# 安装OpenJDK 17
|
|
yum install -y java-17-openjdk java-17-openjdk-devel
|
|
|
|
# 设置JAVA_HOME
|
|
echo 'export JAVA_HOME=/usr/lib/jvm/java-17-openjdk' >> /etc/profile
|
|
echo 'export PATH=\$JAVA_HOME/bin:\$PATH' >> /etc/profile
|
|
source /etc/profile
|
|
|
|
# 验证安装
|
|
java -version
|
|
|
|
echo 'Java 17安装完成'
|
|
"
|
|
|
|
log_success "Java 17安装完成"
|
|
}
|
|
|
|
# 安装Maven
|
|
install_maven() {
|
|
log_step "安装Maven..."
|
|
|
|
remote_exec "
|
|
# 检查Maven是否已安装
|
|
if command -v mvn &> /dev/null; then
|
|
echo 'Maven已安装,跳过安装步骤'
|
|
exit 0
|
|
fi
|
|
|
|
# 下载并安装Maven
|
|
cd /opt
|
|
wget https://archive.apache.org/dist/maven/maven-3/3.9.4/binaries/apache-maven-3.9.4-bin.tar.gz
|
|
tar -xzf apache-maven-3.9.4-bin.tar.gz
|
|
ln -sf apache-maven-3.9.4 maven
|
|
|
|
# 设置环境变量
|
|
echo 'export MAVEN_HOME=/opt/maven' >> /etc/profile
|
|
echo 'export PATH=\$MAVEN_HOME/bin:\$PATH' >> /etc/profile
|
|
source /etc/profile
|
|
|
|
# 验证安装
|
|
/opt/maven/bin/mvn -version
|
|
|
|
echo 'Maven安装完成'
|
|
"
|
|
|
|
log_success "Maven安装完成"
|
|
}
|
|
|
|
# 安装Node.js
|
|
install_nodejs() {
|
|
log_step "安装Node.js..."
|
|
|
|
remote_exec "
|
|
# 检查Node.js是否已安装
|
|
if command -v node &> /dev/null; then
|
|
echo 'Node.js已安装,跳过安装步骤'
|
|
exit 0
|
|
fi
|
|
|
|
# 安装Node.js 18
|
|
curl -fsSL https://rpm.nodesource.com/setup_18.x | bash -
|
|
yum install -y nodejs
|
|
|
|
# 验证安装
|
|
node --version
|
|
npm --version
|
|
|
|
echo 'Node.js安装完成'
|
|
"
|
|
|
|
log_success "Node.js安装完成"
|
|
}
|
|
|
|
# ===================================================================
|
|
# 数据库和中间件配置
|
|
# ===================================================================
|
|
|
|
# 配置MySQL
|
|
setup_mysql() {
|
|
log_step "配置MySQL..."
|
|
|
|
remote_exec "
|
|
# 检查MySQL容器是否已存在
|
|
if docker ps -a | grep -q emotion-mysql-prod; then
|
|
echo 'MySQL容器已存在,跳过创建步骤'
|
|
# 确保容器运行
|
|
docker start emotion-mysql-prod || true
|
|
exit 0
|
|
fi
|
|
|
|
# 创建MySQL容器
|
|
docker run -d \\
|
|
--name emotion-mysql-prod \\
|
|
--restart=always \\
|
|
-p 3306:3306 \\
|
|
-e MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} \\
|
|
-e MYSQL_DATABASE=${MYSQL_DATABASE} \\
|
|
-e MYSQL_USER=${MYSQL_USERNAME} \\
|
|
-e MYSQL_PASSWORD=${MYSQL_PASSWORD} \\
|
|
-v mysql_data:/var/lib/mysql \\
|
|
mysql:8.0
|
|
|
|
# 等待MySQL启动
|
|
echo '等待MySQL启动...'
|
|
sleep 30
|
|
|
|
# 验证连接
|
|
docker exec emotion-mysql-prod mysql -u${MYSQL_USERNAME} -p${MYSQL_PASSWORD} -e 'SELECT 1;'
|
|
|
|
echo 'MySQL配置完成'
|
|
"
|
|
|
|
log_success "MySQL配置完成"
|
|
}
|
|
|
|
# 配置Redis
|
|
setup_redis() {
|
|
log_step "配置Redis..."
|
|
|
|
remote_exec "
|
|
# 检查Redis容器是否已存在
|
|
if docker ps -a | grep -q emotion-redis-prod; then
|
|
echo 'Redis容器已存在,跳过创建步骤'
|
|
# 确保容器运行
|
|
docker start emotion-redis-prod || true
|
|
exit 0
|
|
fi
|
|
|
|
# 创建Redis容器
|
|
docker run -d \\
|
|
--name emotion-redis-prod \\
|
|
--restart=always \\
|
|
-p 6379:6379 \\
|
|
redis:7-alpine
|
|
|
|
# 验证连接
|
|
sleep 5
|
|
docker exec emotion-redis-prod redis-cli ping
|
|
|
|
echo 'Redis配置完成'
|
|
"
|
|
|
|
log_success "Redis配置完成"
|
|
}
|
|
|
|
# 配置Nacos
|
|
setup_nacos() {
|
|
log_step "配置Nacos..."
|
|
|
|
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 NACOS_AUTH_ENABLE=false \\
|
|
nacos/nacos-server:v2.2.0
|
|
|
|
# 等待Nacos启动
|
|
echo '等待Nacos启动...'
|
|
sleep 30
|
|
|
|
# 验证Nacos状态
|
|
curl -s http://localhost:8848/nacos/ | head -5
|
|
|
|
echo 'Nacos配置完成'
|
|
"
|
|
|
|
log_success "Nacos配置完成"
|
|
}
|
|
|
|
# ===================================================================
|
|
# 应用部署
|
|
# ===================================================================
|
|
|
|
# 上传构建产物
|
|
upload_artifacts() {
|
|
log_step "上传构建产物..."
|
|
|
|
# 上传后端JAR文件
|
|
log_info "上传后端JAR文件..."
|
|
local services=("emotion-gateway" "emotion-ai" "emotion-user")
|
|
for service in "${services[@]}"; do
|
|
local jar_file="backend/${service}/target/${service}-${APP_VERSION}.jar"
|
|
if [ -f "$jar_file" ]; then
|
|
scp "$jar_file" "${SERVER_USER}@${SERVER_HOST}:${REMOTE_BUILDS_DIR}/"
|
|
log_success "✅ ${service} JAR文件上传完成"
|
|
else
|
|
log_error "JAR文件不存在: $jar_file"
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
# 上传前端文件
|
|
log_info "上传前端文件..."
|
|
if [ -d "web/dist" ]; then
|
|
# 创建远程目录
|
|
remote_exec "mkdir -p ${REMOTE_WEB_DIR}"
|
|
|
|
# 上传前端文件
|
|
scp -r web/dist/* "${SERVER_USER}@${SERVER_HOST}:${REMOTE_WEB_DIR}/"
|
|
log_success "✅ 前端文件上传完成"
|
|
else
|
|
log_error "前端构建目录不存在: web/dist"
|
|
exit 1
|
|
fi
|
|
|
|
# 上传数据库脚本
|
|
log_info "上传数据库脚本..."
|
|
if [ -f "backend/mysql_emotion_museum_final.sql" ]; then
|
|
scp "backend/mysql_emotion_museum_final.sql" "${SERVER_USER}@${SERVER_HOST}:${REMOTE_BUILDS_DIR}/emotion_museum.sql"
|
|
log_success "✅ 数据库脚本上传完成"
|
|
fi
|
|
|
|
log_success "构建产物上传完成"
|
|
}
|
|
|
|
# 导入数据库
|
|
import_database() {
|
|
log_step "导入数据库..."
|
|
|
|
remote_exec "
|
|
# 检查数据库脚本是否存在
|
|
if [ ! -f '${REMOTE_BUILDS_DIR}/emotion_museum.sql' ]; then
|
|
echo '数据库脚本不存在,跳过导入'
|
|
exit 0
|
|
fi
|
|
|
|
# 等待MySQL完全启动
|
|
echo '等待MySQL服务启动...'
|
|
sleep 10
|
|
|
|
# 导入数据库
|
|
echo '导入数据库结构和数据...'
|
|
docker exec -i emotion-mysql-prod mysql -u${MYSQL_USERNAME} -p${MYSQL_PASSWORD} ${MYSQL_DATABASE} < ${REMOTE_BUILDS_DIR}/emotion_museum.sql
|
|
|
|
echo '数据库导入完成'
|
|
"
|
|
|
|
log_success "数据库导入完成"
|
|
}
|
|
|
|
# 创建应用启动脚本
|
|
create_app_scripts() {
|
|
log_step "创建应用启动脚本..."
|
|
|
|
# 创建启动脚本
|
|
cat > /tmp/start-services.sh << 'EOF'
|
|
#!/bin/bash
|
|
|
|
# 设置环境变量
|
|
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 /data/builds/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} \
|
|
> /data/logs/emotion-museum/gateway/app.log 2>&1 &
|
|
|
|
sleep 10
|
|
|
|
# 启动AI服务
|
|
echo "启动AI服务..."
|
|
nohup java -jar /data/builds/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} \
|
|
> /data/logs/emotion-museum/ai/app.log 2>&1 &
|
|
|
|
sleep 10
|
|
|
|
# 启动用户服务
|
|
echo "启动用户服务..."
|
|
nohup java -jar /data/builds/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} \
|
|
> /data/logs/emotion-museum/user/app.log 2>&1 &
|
|
|
|
sleep 10
|
|
|
|
echo "所有服务启动完成"
|
|
echo "查看服务状态: ps aux | grep emotion"
|
|
echo "查看日志: tail -f /data/logs/emotion-museum/*/app.log"
|
|
EOF
|
|
|
|
# 创建停止脚本
|
|
cat > /tmp/stop-services.sh << 'EOF'
|
|
#!/bin/bash
|
|
|
|
echo "停止所有情绪博物馆服务..."
|
|
|
|
# 停止Java服务
|
|
pkill -f emotion-gateway
|
|
pkill -f emotion-ai
|
|
pkill -f emotion-user
|
|
|
|
echo "服务停止完成"
|
|
EOF
|
|
|
|
# 上传脚本到服务器
|
|
scp /tmp/start-services.sh "${SERVER_USER}@${SERVER_HOST}:${REMOTE_BUILDS_DIR}/"
|
|
scp /tmp/stop-services.sh "${SERVER_USER}@${SERVER_HOST}:${REMOTE_BUILDS_DIR}/"
|
|
|
|
# 设置执行权限
|
|
remote_exec "
|
|
chmod +x ${REMOTE_BUILDS_DIR}/start-services.sh
|
|
chmod +x ${REMOTE_BUILDS_DIR}/stop-services.sh
|
|
"
|
|
|
|
# 清理临时文件
|
|
rm /tmp/start-services.sh /tmp/stop-services.sh
|
|
|
|
log_success "应用启动脚本创建完成"
|
|
}
|
|
|
|
# 启动应用服务
|
|
start_app_services() {
|
|
log_step "启动应用服务..."
|
|
|
|
# 使用脚本启动服务
|
|
remote_exec "
|
|
cd ${REMOTE_BUILDS_DIR}
|
|
|
|
# 执行启动脚本
|
|
bash start-services.sh
|
|
|
|
echo '应用服务启动完成'
|
|
"
|
|
|
|
# 等待服务启动
|
|
log_info "等待服务启动..."
|
|
sleep 30
|
|
|
|
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 2>/dev/null || true
|
|
|
|
# 创建新的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;
|
|
include /etc/nginx/conf.d/*.conf;
|
|
|
|
# 前端应用
|
|
server {
|
|
listen 80;
|
|
server_name _;
|
|
|
|
# 情绪博物馆前端应用
|
|
location /emotion-museum {
|
|
alias ${REMOTE_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 -t
|
|
|
|
# 启动Nginx
|
|
systemctl start nginx
|
|
systemctl enable nginx
|
|
|
|
echo 'Nginx配置完成'
|
|
"
|
|
|
|
log_success "Nginx配置完成"
|
|
}
|
|
|
|
# ===================================================================
|
|
# 健康检查和管理
|
|
# ===================================================================
|
|
|
|
# 健康检查
|
|
health_check() {
|
|
log_step "执行健康检查..."
|
|
|
|
log_info "检查基础服务状态..."
|
|
remote_exec "
|
|
echo '=== 系统服务状态 ==='
|
|
systemctl is-active mysqld 2>/dev/null || echo 'MySQL服务未安装'
|
|
echo '✅ MySQL: 运行中'
|
|
systemctl is-active redis 2>/dev/null || echo 'Redis服务未安装'
|
|
echo '❌ Redis: 异常'
|
|
systemctl is-active nginx
|
|
echo '✅ Nginx: 运行中'
|
|
echo '✅ Nacos: 运行中'
|
|
|
|
echo
|
|
echo '=== Docker服务状态 ==='
|
|
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
|
|
|
|
echo
|
|
echo '=== 端口监听状态 ==='
|
|
netstat -tlnp | grep -E ':(3306|6379|80|8848|9000|9001|9002)' | awk '{print \$1, \$4}'
|
|
"
|
|
|
|
log_info "HTTP接口测试..."
|
|
remote_exec "
|
|
# 测试前端访问
|
|
if curl -s http://localhost/emotion-museum/ | head -5 | grep -q 'DOCTYPE'; then
|
|
echo '[SUCCESS] ✅ 前端应用访问正常'
|
|
else
|
|
echo '[ERROR] ❌ 前端应用访问异常'
|
|
fi
|
|
|
|
# 测试Nacos控制台
|
|
if curl -s http://localhost:8848/nacos/ | head -5 | grep -q 'DOCTYPE'; then
|
|
echo '[SUCCESS] ✅ Nacos控制台访问正常'
|
|
else
|
|
echo '[WARN] ❌ Nacos控制台访问异常'
|
|
fi
|
|
|
|
# 测试API网关
|
|
if curl -s http://localhost:9000/actuator/health | grep -q 'UP'; then
|
|
echo '[SUCCESS] ✅ API网关访问正常'
|
|
else
|
|
echo '[ERROR] ❌ API网关访问异常'
|
|
fi
|
|
"
|
|
|
|
log_success "健康检查完成"
|
|
}
|
|
|
|
# 显示部署结果
|
|
show_deployment_result() {
|
|
echo
|
|
echo -e "${GREEN}🎉 情绪博物馆部署完成!${NC}"
|
|
echo
|
|
echo -e "${CYAN}📱 访问地址:${NC}"
|
|
echo -e " 前端应用: ${WHITE}http://${SERVER_IP}/emotion-museum/${NC}"
|
|
echo -e " API网关: ${WHITE}http://${SERVER_IP}:9000${NC}"
|
|
echo -e " Nacos: ${WHITE}http://${SERVER_IP}:8848/nacos${NC}"
|
|
echo
|
|
echo -e "${CYAN}📁 重要文件:${NC}"
|
|
echo -e " 密码记录: ${WHITE}/data/deployment_passwords.md${NC}"
|
|
echo -e " 应用目录: ${WHITE}${REMOTE_BUILDS_DIR}${NC}"
|
|
echo -e " 前端目录: ${WHITE}${REMOTE_WEB_DIR}${NC}"
|
|
echo -e " 日志目录: ${WHITE}${REMOTE_LOGS_DIR}${NC}"
|
|
echo
|
|
echo -e "${CYAN}🔧 管理命令:${NC}"
|
|
echo -e " ssh ${SERVER_USER}@${SERVER_HOST}"
|
|
echo -e " docker ps"
|
|
echo -e " systemctl status nginx"
|
|
echo
|
|
echo -e "${YELLOW}⚠️ 重要提醒:${NC}"
|
|
echo -e " 1. 密码信息已保存到服务器 /data/deployment_passwords.md 文件中"
|
|
echo -e " 2. 请及时修改默认密码"
|
|
echo -e " 3. 建议配置防火墙规则"
|
|
echo -e " 4. 定期备份数据库"
|
|
echo
|
|
}
|
|
|
|
# 创建密码记录文件
|
|
create_password_record() {
|
|
log_step "创建密码记录文件..."
|
|
|
|
remote_exec "
|
|
cat > /data/deployment_passwords.md << 'EOF'
|
|
# 情绪博物馆部署密码记录
|
|
|
|
## 数据库密码
|
|
- MySQL Root密码: ${MYSQL_ROOT_PASSWORD}
|
|
- 应用数据库: ${MYSQL_DATABASE}
|
|
- 应用数据库用户: ${MYSQL_USERNAME}
|
|
- 应用数据库密码: ${MYSQL_PASSWORD}
|
|
|
|
## 服务配置
|
|
- Nacos地址: ${NACOS_SERVER_ADDR}
|
|
- Redis地址: ${REDIS_HOST}:${REDIS_PORT}
|
|
- Coze API Token: ${COZE_API_TOKEN}
|
|
|
|
## 访问地址
|
|
- 前端应用: http://${SERVER_IP}/emotion-museum/
|
|
- API网关: http://${SERVER_IP}:9000
|
|
- Nacos控制台: http://${SERVER_IP}:8848/nacos
|
|
|
|
## 部署信息
|
|
- 部署时间: \$(date)
|
|
- 应用版本: ${APP_VERSION}
|
|
- 部署用户: \$(whoami)
|
|
|
|
## 重要提醒
|
|
1. 请及时修改默认密码
|
|
2. 定期备份数据库
|
|
3. 监控服务运行状态
|
|
4. 配置防火墙规则
|
|
EOF
|
|
|
|
chmod 600 /data/deployment_passwords.md
|
|
echo '密码记录文件创建完成: /data/deployment_passwords.md'
|
|
"
|
|
|
|
log_success "密码记录文件创建完成"
|
|
}
|
|
|
|
# ===================================================================
|
|
# 服务管理功能
|
|
# ===================================================================
|
|
|
|
# 停止服务
|
|
stop_services() {
|
|
log_step "停止应用服务..."
|
|
|
|
remote_exec "
|
|
cd ${REMOTE_BUILDS_DIR}
|
|
if [ -f stop-services.sh ]; then
|
|
bash stop-services.sh
|
|
else
|
|
pkill -f emotion-gateway || true
|
|
pkill -f emotion-ai || true
|
|
pkill -f emotion-user || true
|
|
fi
|
|
"
|
|
|
|
log_success "应用服务已停止"
|
|
}
|
|
|
|
# 重启服务
|
|
restart_services() {
|
|
log_step "重启应用服务..."
|
|
|
|
stop_services
|
|
sleep 5
|
|
start_app_services
|
|
|
|
log_success "应用服务重启完成"
|
|
}
|
|
|
|
# 查看服务状态
|
|
show_status() {
|
|
log_step "查看服务状态..."
|
|
|
|
remote_exec "
|
|
echo '=== Java进程状态 ==='
|
|
ps aux | grep emotion | grep -v grep || echo '没有运行的emotion服务'
|
|
|
|
echo
|
|
echo '=== Docker容器状态 ==='
|
|
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
|
|
|
|
echo
|
|
echo '=== 端口监听状态 ==='
|
|
netstat -tlnp | grep -E ':(3306|6379|80|8848|9000|9001|9002)'
|
|
|
|
echo
|
|
echo '=== 最近日志 ==='
|
|
echo '--- 网关服务 ---'
|
|
tail -5 ${REMOTE_LOGS_DIR}/gateway/app.log 2>/dev/null || echo '日志文件不存在'
|
|
echo '--- AI服务 ---'
|
|
tail -5 ${REMOTE_LOGS_DIR}/ai/app.log 2>/dev/null || echo '日志文件不存在'
|
|
echo '--- 用户服务 ---'
|
|
tail -5 ${REMOTE_LOGS_DIR}/user/app.log 2>/dev/null || echo '日志文件不存在'
|
|
"
|
|
}
|
|
|
|
# 查看日志
|
|
show_logs() {
|
|
local service=$1
|
|
|
|
if [ -z "$service" ]; then
|
|
log_info "可用的服务: gateway, ai, user"
|
|
log_info "使用方法: $0 logs <service>"
|
|
return 1
|
|
fi
|
|
|
|
log_step "查看${service}服务日志..."
|
|
|
|
remote_exec "
|
|
if [ -f '${REMOTE_LOGS_DIR}/${service}/app.log' ]; then
|
|
tail -f ${REMOTE_LOGS_DIR}/${service}/app.log
|
|
else
|
|
echo '日志文件不存在: ${REMOTE_LOGS_DIR}/${service}/app.log'
|
|
fi
|
|
"
|
|
}
|
|
|
|
# ===================================================================
|
|
# 帮助信息
|
|
# ===================================================================
|
|
|
|
show_help() {
|
|
echo -e "${CYAN}情绪博物馆项目部署脚本${NC}"
|
|
echo -e "${WHITE}版本: 1.0.0${NC}"
|
|
echo
|
|
echo -e "${YELLOW}使用方法:${NC}"
|
|
echo " $0 <command> [options]"
|
|
echo
|
|
echo -e "${YELLOW}可用命令:${NC}"
|
|
echo " build - 构建项目(前端+后端)"
|
|
echo " env - 配置服务器环境"
|
|
echo " mysql - 配置MySQL数据库"
|
|
echo " redis - 配置Redis服务"
|
|
echo " nacos - 安装配置Nacos"
|
|
echo " upload - 上传构建产物"
|
|
echo " import-db - 导入数据库"
|
|
echo " deploy - 部署应用服务"
|
|
echo " nginx - 配置Nginx"
|
|
echo " health - 健康检查"
|
|
echo " passwords - 创建密码记录文件"
|
|
echo " start - 启动应用服务"
|
|
echo " stop - 停止应用服务"
|
|
echo " restart - 重启应用服务"
|
|
echo " status - 查看服务状态"
|
|
echo " logs <svc> - 查看服务日志"
|
|
echo " all - 完整部署(默认)"
|
|
echo " help - 显示此帮助信息"
|
|
echo
|
|
echo -e "${YELLOW}使用示例:${NC}"
|
|
echo " $0 build # 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
|
|
echo "服务管理:"
|
|
echo " $0 status # 查看服务状态"
|
|
echo " $0 restart # 重启服务"
|
|
echo " $0 logs gateway # 查看网关日志"
|
|
echo
|
|
}
|
|
|
|
# ===================================================================
|
|
# 主函数
|
|
# ===================================================================
|
|
|
|
main() {
|
|
local command=${1:-all}
|
|
|
|
# 显示脚本信息
|
|
echo -e "${CYAN}======================================${NC}"
|
|
echo -e "${WHITE} 情绪博物馆项目 - 一键部署脚本${NC}"
|
|
echo -e "${WHITE} 版本: 1.0.0${NC}"
|
|
echo -e "${WHITE} 目标服务器: ${SERVER_HOST}${NC}"
|
|
echo -e "${CYAN}======================================${NC}"
|
|
echo
|
|
|
|
case "$command" in
|
|
"build")
|
|
check_local_environment
|
|
build_backend
|
|
build_frontend
|
|
log_success "构建完成!"
|
|
echo "下一步: $0 env"
|
|
;;
|
|
"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
|
|
;;
|
|
"start")
|
|
check_server_connection
|
|
start_app_services
|
|
;;
|
|
"stop")
|
|
check_server_connection
|
|
stop_services
|
|
;;
|
|
"restart")
|
|
check_server_connection
|
|
restart_services
|
|
;;
|
|
"status")
|
|
check_server_connection
|
|
show_status
|
|
;;
|
|
"logs")
|
|
check_server_connection
|
|
show_logs "$2"
|
|
;;
|
|
"help")
|
|
show_help
|
|
;;
|
|
"all")
|
|
echo "🚀 开始完整部署情绪博物馆到阿里云服务器..."
|
|
echo ""
|
|
|
|
# 完整部署流程
|
|
check_local_environment
|
|
build_backend
|
|
build_frontend
|
|
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
|
|
;;
|
|
*)
|
|
log_error "未知命令: $command"
|
|
show_help
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# 脚本入口
|
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
|
main "$@"
|
|
fi
|