Files
happy-life-star/deploy-final.sh
T

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