Files
happy-life-star/deploy-aliyun-optimized.sh
T

1129 lines
33 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# 情绪博物馆阿里云服务器优化部署脚本
# 适配要求:MySQL/Redis/Nacos直接安装,应用服务使用Docker
# 分步骤执行,避免超时,记录密码到MD文件
# 作者: EmotionMuseum Team
# 日期: 2025-07-13
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
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"
LOGS_DIR="/data/logs/emotion-museum"
CONFIG_FILE="/data/deployment_passwords.md"
# 生成密码函数
generate_password() {
echo $(openssl rand -base64 32 | tr -d "=+/" | cut -c1-20)
}
# 日志函数
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"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
log_debug() {
echo -e "${CYAN}[DEBUG]${NC} $1"
}
# 远程执行命令
remote_exec() {
local command="$1"
local timeout="${2:-60}"
ssh -o StrictHostKeyChecking=no -o ConnectTimeout="$timeout" -o ServerAliveInterval=30 -o ServerAliveCountMax=3 "${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_success "服务器连接正常"
# 显示服务器基本信息
log_info "服务器信息:"
remote_exec "echo ' 内核版本: '$(uname -r)"
remote_exec "echo ' 当前用户: '$(whoami)"
remote_exec "echo ' 当前时间: '$(date)"
}
# 创建服务器目录结构
setup_directories() {
log_step "创建服务器目录结构..."
remote_exec "mkdir -p ${PROGRAMS_DIR}/{java,maven,nodejs,nacos}"
remote_exec "mkdir -p ${BUILDS_DIR}"
remote_exec "mkdir -p ${WEB_DIR}"
remote_exec "mkdir -p ${LOGS_DIR}/{mysql,redis,nacos,docker,nginx}"
remote_exec "mkdir -p /data/backup"
remote_exec "mkdir -p /data/ssl"
log_success "目录结构创建完成"
remote_exec "tree /data -L 2 2>/dev/null || ls -la /data"
}
# 安装基础软件包
install_basic_packages() {
log_step "安装基础软件包..."
remote_exec "yum update -y"
remote_exec "yum install -y wget curl git unzip vim net-tools tree htop"
log_success "基础软件包安装完成"
}
# 安装Docker
install_docker() {
log_step "安装Docker..."
remote_exec "
if ! command -v docker &> /dev/null; then
echo '开始安装Docker...'
curl -fsSL https://get.docker.com | sh
systemctl start docker
systemctl enable docker
# 安装Docker Compose
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
ln -sf /usr/local/bin/docker-compose /usr/bin/docker-compose
echo 'Docker和Docker Compose安装完成'
docker --version
docker-compose --version
else
echo 'Docker已安装: '$(docker --version)
if ! command -v docker-compose &> /dev/null; then
echo '安装Docker Compose...'
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
ln -sf /usr/local/bin/docker-compose /usr/bin/docker-compose
fi
echo 'Docker Compose: '$(docker-compose --version)
fi
"
log_success "Docker安装检查完成"
}
# 安装Java环境
install_java() {
log_step "安装Java环境..."
remote_exec "
if ! java -version 2>&1 | grep -q '17'; then
echo '安装Java 17...'
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
java -version
"
log_success "Java环境检查完成"
}
# 安装Maven环境
install_maven() {
log_step "安装Maven环境..."
remote_exec "
if ! command -v mvn &> /dev/null; then
echo '安装Maven...'
MAVEN_VERSION='3.9.5'
cd /tmp
wget https://archive.apache.org/dist/maven/maven-3/\${MAVEN_VERSION}/binaries/apache-maven-\${MAVEN_VERSION}-bin.tar.gz
tar -xzf apache-maven-\${MAVEN_VERSION}-bin.tar.gz
mv apache-maven-\${MAVEN_VERSION} ${PROGRAMS_DIR}/maven
# 配置环境变量
echo 'export MAVEN_HOME=${PROGRAMS_DIR}/maven' >> /etc/profile
echo 'export PATH=\$MAVEN_HOME/bin:\$PATH' >> /etc/profile
source /etc/profile
rm -f apache-maven-\${MAVEN_VERSION}-bin.tar.gz
echo 'Maven安装完成'
else
echo 'Maven已安装'
fi
mvn -version 2>/dev/null || echo 'Maven需要重新登录生效'
"
log_success "Maven环境检查完成"
}
# 安装Node.js环境
install_nodejs() {
log_step "安装Node.js环境..."
remote_exec "
if ! command -v node &> /dev/null; then
echo '安装Node.js 18...'
curl -fsSL https://rpm.nodesource.com/setup_18.x | bash -
yum install -y nodejs
# 配置npm镜像
npm config set registry https://registry.npmmirror.com
echo 'Node.js安装完成'
else
echo 'Node.js已安装'
fi
node --version
npm --version
"
log_success "Node.js环境检查完成"
}
# 验证MySQL连接
verify_mysql() {
log_step "验证MySQL连接..."
# 首先检查是否有Docker容器运行MySQL
if remote_exec "docker ps | grep mysql > /dev/null"; then
log_info "检测到Docker MySQL容器"
if remote_exec "docker exec \$(docker ps | grep mysql | awk '{print \$1}') mysql -u root -p${MYSQL_ROOT_PASSWORD} -e 'SELECT 1;' &>/dev/null"; then
log_success "Docker MySQL连接正常,密码正确"
return 0
else
log_error "Docker MySQL连接失败,请检查密码"
return 1
fi
# 检查本地MySQL服务
elif remote_exec "mysql -u root -p${MYSQL_ROOT_PASSWORD} -e 'SELECT 1;' &>/dev/null"; then
log_success "本地MySQL连接正常,密码正确"
return 0
else
log_error "MySQL连接失败,请检查密码或MySQL服务状态"
remote_exec "systemctl status mysqld || systemctl status mysql || echo 'No local MySQL service'"
return 1
fi
}
# 配置MySQL数据库
setup_mysql() {
log_step "配置MySQL数据库..."
# 首先验证连接
if ! verify_mysql; then
log_error "MySQL验证失败,请检查MySQL服务和密码"
exit 1
fi
# 创建应用数据库和用户
log_info "创建应用数据库和用户..."
# 检查是否是Docker MySQL
if remote_exec "docker ps | grep mysql > /dev/null"; then
log_info "使用Docker MySQL容器"
remote_exec "
docker exec \$(docker ps | grep mysql | awk '{print \$1}') 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;
SELECT 'MySQL数据库配置完成' AS status;
\"
"
else
log_info "使用本地MySQL服务"
remote_exec "
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;
SELECT 'MySQL数据库配置完成' AS status;
\"
"
fi
log_success "MySQL数据库配置完成"
}
# 配置Redis服务
setup_redis() {
log_step "配置Redis服务..."
# 检查是否已有Docker Redis容器运行
if remote_exec "docker ps | grep redis > /dev/null"; then
log_info "检测到Docker Redis容器正在运行"
# 获取Redis容器信息
REDIS_CONTAINER=$(remote_exec "docker ps | grep redis | awk '{print \$1}'")
log_info "Redis容器ID: $REDIS_CONTAINER"
# 测试Redis连接
if remote_exec "docker exec \$(docker ps | grep redis | awk '{print \$1}') redis-cli ping 2>/dev/null | grep -q PONG"; then
log_success "Docker Redis服务正常运行"
else
log_warn "Docker Redis可能需要密码,尝试重启容器"
remote_exec "docker restart \$(docker ps | grep redis | awk '{print \$1}')"
sleep 5
fi
# 记录Redis信息(从Docker环境变量获取)
REDIS_PASSWORD=$(remote_exec "docker exec \$(docker ps | grep redis | awk '{print \$1}') env | grep REDIS_PASSWORD | cut -d'=' -f2 2>/dev/null || echo 'no-password'")
echo "REDIS_PASSWORD=${REDIS_PASSWORD}" >> /tmp/passwords.txt
log_success "Docker Redis配置确认完成"
return 0
fi
# 如果没有Docker Redis,安装本地Redis
log_info "安装本地Redis服务..."
# 生成Redis密码
REDIS_PASSWORD=$(generate_password)
remote_exec "
# 检查Redis是否已安装
if ! command -v redis-server &> /dev/null; then
echo '安装Redis...'
yum install -y redis
else
echo 'Redis已安装'
fi
# 配置Redis
cp /etc/redis.conf /etc/redis.conf.backup 2>/dev/null || true
sed -i 's/^# requirepass foobared/requirepass ${REDIS_PASSWORD}/' /etc/redis.conf
sed -i 's/^bind 127.0.0.1/bind 0.0.0.0/' /etc/redis.conf
# 启动Redis服务
systemctl start redis
systemctl enable redis
echo 'Redis配置完成,密码: ${REDIS_PASSWORD}'
"
# 记录Redis密码
echo "REDIS_PASSWORD=${REDIS_PASSWORD}" >> /tmp/passwords.txt
log_success "本地Redis配置完成,密码已生成"
}
# 安装配置Nacos
setup_nacos() {
log_step "使用Docker安装配置Nacos..."
# 检查是否已有Nacos容器运行
if remote_exec "docker ps | grep nacos > /dev/null"; then
log_info "检测到Nacos容器正在运行"
if remote_exec "curl -s http://localhost:8848/nacos > /dev/null"; then
log_success "Nacos服务正常运行"
return 0
else
log_warn "Nacos容器存在但服务异常,重启容器"
remote_exec "docker restart \$(docker ps | grep nacos | awk '{print \$1}')"
sleep 10
fi
fi
log_info "创建Nacos Docker配置..."
# 创建Nacos配置目录
remote_exec "mkdir -p ${PROGRAMS_DIR}/nacos/{conf,data,logs}"
# 创建Nacos配置文件
cat > /tmp/nacos-application.properties << 'EOF'
# Nacos配置文件
server.servlet.contextPath=/nacos
server.port=8848
# 数据库配置 - 使用MySQL
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://host.docker.internal:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai
db.user.0=emotion
db.password.0=EmotionDB2024!
# JVM配置
nacos.inetutils.prefer-hostname-over-ip=false
nacos.inetutils.ip-address=0.0.0.0
# 安全配置
nacos.security.ignore.urls=/,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-ui/public/**,/v1/auth/**,/v1/console/health/**,/actuator/**,/v1/console/server/**
# 集群配置(单机模式)
nacos.naming.distro.taskDispatchThreadCount=10
nacos.naming.distro.taskDispatchPeriod=200
nacos.naming.distro.batchSyncKeyCount=1000
nacos.naming.distro.initDataRatio=0.9
nacos.naming.distro.syncRetryDelay=5000
nacos.naming.data.warmup=true
nacos.naming.expireInstance=true
# 日志配置
logging.level.root=INFO
logging.level.org.springframework=INFO
logging.level.com.alibaba.nacos=INFO
EOF
# 上传配置文件
remote_copy "/tmp/nacos-application.properties" "${PROGRAMS_DIR}/nacos/conf/application.properties"
rm /tmp/nacos-application.properties
# 创建Nacos数据库
log_info "创建Nacos数据库..."
if remote_exec "docker ps | grep mysql > /dev/null"; then
remote_exec "
docker exec \$(docker ps | grep mysql | awk '{print \$1}') mysql -u root -p${MYSQL_ROOT_PASSWORD} -e \"
CREATE DATABASE IF NOT EXISTS nacos_config CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
GRANT ALL PRIVILEGES ON nacos_config.* TO 'emotion'@'%';
FLUSH PRIVILEGES;
\"
"
fi
# 启动Nacos容器
log_info "启动Nacos Docker容器..."
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 SPRING_DATASOURCE_PLATFORM=mysql \\
-e MYSQL_SERVICE_HOST=host.docker.internal \\
-e MYSQL_SERVICE_PORT=3306 \\
-e MYSQL_SERVICE_DB_NAME=nacos_config \\
-e MYSQL_SERVICE_USER=emotion \\
-e MYSQL_SERVICE_PASSWORD=EmotionDB2024! \\
-e NACOS_AUTH_ENABLE=false \\
-v ${PROGRAMS_DIR}/nacos/conf:/home/nacos/conf \\
-v ${PROGRAMS_DIR}/nacos/data:/home/nacos/data \\
-v ${PROGRAMS_DIR}/nacos/logs:/home/nacos/logs \\
--add-host=host.docker.internal:host-gateway \\
nacos/nacos-server:v2.2.0
echo 'Nacos容器启动完成'
"
# 等待Nacos启动
log_info "等待Nacos服务启动..."
sleep 30
# 验证Nacos服务
if remote_exec "curl -s http://localhost:8848/nacos > /dev/null"; then
log_success "Nacos服务启动成功"
else
log_warn "Nacos服务可能还在启动中,请稍后检查"
fi
log_success "Docker Nacos安装配置完成"
}
# 上传构建产物
upload_artifacts() {
log_step "上传构建产物..."
# 检查构建产物是否存在
if [ ! -d "build-output" ]; then
log_error "构建产物不存在,请先运行构建命令"
log_info "可以运行: ./package.sh 或 mvn clean package"
exit 1
fi
# 上传JAR文件
if [ -d "build-output/jars" ]; then
log_info "上传JAR文件..."
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
log_info "上传前端文件..."
remote_exec "rm -rf ${WEB_DIR}/*"
# 直接上传整个目录
remote_copy "build-output/web/" "${WEB_DIR}/"
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_success "构建产物上传完成"
}
# 导入数据库
import_database() {
log_step "导入数据库..."
if ! remote_exec "[ -f /tmp/mysql_emotion_museum_final.sql ]"; then
log_error "数据库脚本不存在,跳过导入"
return 1
fi
# 检查是否是Docker MySQL
if remote_exec "docker ps | grep mysql > /dev/null"; then
log_info "使用Docker MySQL导入数据库..."
remote_exec "
echo '开始导入数据库到Docker MySQL...'
docker exec -i \$(docker ps | grep mysql | awk '{print \$1}') mysql -u root -p${MYSQL_ROOT_PASSWORD} emotion_museum < /tmp/mysql_emotion_museum_final.sql
echo '数据库导入完成'
# 验证导入结果
docker exec \$(docker ps | grep mysql | awk '{print \$1}') mysql -u root -p${MYSQL_ROOT_PASSWORD} emotion_museum -e 'SHOW TABLES;'
"
else
log_info "使用本地MySQL导入数据库..."
remote_exec "
echo '开始导入数据库到本地MySQL...'
mysql -u root -p${MYSQL_ROOT_PASSWORD} emotion_museum < /tmp/mysql_emotion_museum_final.sql
echo '数据库导入完成'
# 验证导入结果
mysql -u root -p${MYSQL_ROOT_PASSWORD} emotion_museum -e 'SHOW TABLES;'
"
fi
log_success "数据库导入完成"
}
# 创建应用启动脚本(不使用Docker)
create_app_scripts() {
log_step "创建应用启动脚本..."
# 创建启动脚本
cat > /tmp/start-services.sh << 'EOF'
#!/bin/bash
# 情绪博物馆应用服务启动脚本
BUILDS_DIR="/data/builds"
LOGS_DIR="/data/logs/emotion-museum"
# 创建日志目录
mkdir -p ${LOGS_DIR}/{gateway,ai,user}
# 设置环境变量
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 ${BUILDS_DIR}/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} \
> ${LOGS_DIR}/gateway/app.log 2>&1 &
sleep 10
# 启动AI服务
echo "启动AI服务..."
nohup java -jar ${BUILDS_DIR}/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} \
> ${LOGS_DIR}/ai/app.log 2>&1 &
sleep 10
# 启动用户服务
echo "启动用户服务..."
nohup java -jar ${BUILDS_DIR}/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} \
> ${LOGS_DIR}/user/app.log 2>&1 &
echo "所有服务启动完成"
echo "查看服务状态: ps aux | grep emotion"
echo "查看日志: tail -f ${LOGS_DIR}/*/app.log"
EOF
# 创建停止脚本
cat > /tmp/stop-services.sh << 'EOF'
#!/bin/bash
echo "停止情绪博物馆应用服务..."
pkill -f emotion-gateway && echo "网关服务已停止"
pkill -f emotion-ai && echo "AI服务已停止"
pkill -f emotion-user && echo "用户服务已停止"
echo "所有服务已停止"
EOF
# 上传脚本
remote_copy "/tmp/start-services.sh" "${BUILDS_DIR}/start-services.sh"
remote_copy "/tmp/stop-services.sh" "${BUILDS_DIR}/stop-services.sh"
# 设置执行权限
remote_exec "chmod +x ${BUILDS_DIR}/start-services.sh ${BUILDS_DIR}/stop-services.sh"
# 清理临时文件
rm /tmp/start-services.sh /tmp/stop-services.sh
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
# 创建新的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;
# 前端应用
server {
listen 80;
server_name _;
# 情绪博物馆前端应用
location /emotion-museum {
alias ${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
systemctl start nginx
systemctl enable nginx
echo 'Nginx配置完成'
"
log_success "Nginx配置完成"
}
# 启动应用服务
start_app_services() {
log_step "启动应用服务..."
# 使用脚本启动服务
remote_exec "
cd ${BUILDS_DIR}
# 执行启动脚本
bash start-services.sh
echo '应用服务启动完成'
"
# 等待服务启动
sleep 15
# 检查服务状态
log_info "检查服务状态..."
remote_exec "ps aux | grep -E 'emotion-(gateway|ai|user)' | grep -v grep || echo '没有找到运行的服务'"
log_success "应用服务启动完成"
}
# 创建密码记录文件
create_password_record() {
log_step "创建密码记录文件..."
# 读取临时密码文件
REDIS_PASSWORD=""
if [ -f "/tmp/passwords.txt" ]; then
REDIS_PASSWORD=$(grep "REDIS_PASSWORD" /tmp/passwords.txt | cut -d'=' -f2)
fi
cat > /tmp/deployment_passwords.md << EOF
# 情绪博物馆部署密码记录
## 服务器信息
- 服务器IP: ${SERVER_IP}
- 部署时间: $(date '+%Y-%m-%d %H:%M:%S')
- 部署用户: ${SERVER_USER}
## 数据库配置
### MySQL
- 端口: 3306
- Root用户: root
- Root密码: ${MYSQL_ROOT_PASSWORD}
- 应用数据库: emotion_museum
- 应用用户: emotion
- 应用密码: EmotionDB2024!
### Redis
- 端口: 6379
- 密码: ${REDIS_PASSWORD:-"未设置或生成失败"}
## 服务端口配置
- Nginx: 80
- MySQL: 3306
- Redis: 6379
- Nacos: 8848
- 网关服务: 9000
- 用户服务: 9001
- AI服务: 9002
## 访问地址
- 前端应用: http://${SERVER_IP}
- API网关: http://${SERVER_IP}:9000
- Nacos控制台: http://${SERVER_IP}:8848/nacos
- 用户名: nacos
- 密码: nacos
## API配置
- Coze API Token: pat_GCR4qKzqpf90wMCvKsldMrB18KG3QsLDci65bZthssKsbLxu8X70BKYumleDcabO
## 目录结构
- 程序目录: ${PROGRAMS_DIR}
- 构建目录: ${BUILDS_DIR}
- 前端目录: ${WEB_DIR}
- 日志目录: ${LOGS_DIR}
- 备份目录: /data/backup
## 管理命令
\`\`\`bash
# 查看服务状态
systemctl status mysqld redis nacos nginx
docker ps
# 查看应用日志
docker logs -f emotion-gateway
docker logs -f emotion-ai
docker logs -f emotion-user
# 重启服务
systemctl restart mysqld redis nacos 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}/nacos/bin/shutdown.sh
\`\`\`
## 备份命令
\`\`\`bash
# 数据库备份
mysqldump -u root -p${MYSQL_ROOT_PASSWORD} emotion_museum > /data/backup/emotion_museum_\$(date +%Y%m%d_%H%M%S).sql
# 配置备份
tar -czf /data/backup/config_\$(date +%Y%m%d_%H%M%S).tar.gz /etc/nginx /etc/redis.conf ${PROGRAMS_DIR}/nacos/conf
\`\`\`
## 安全提醒
⚠️ 重要提醒:
1. 请及时修改默认密码
2. 建议配置防火墙规则
3. 定期备份数据库
4. 监控服务器资源使用情况
## 更新记录
- $(date '+%Y-%m-%d %H:%M:%S'): 初始部署完成
---
**此文件包含敏感信息,请妥善保管!**
EOF
# 上传密码记录文件
remote_copy "/tmp/deployment_passwords.md" "${CONFIG_FILE}"
rm /tmp/deployment_passwords.md
# 清理临时密码文件
rm -f /tmp/passwords.txt
log_success "密码记录文件已创建: ${CONFIG_FILE}"
}
# 健康检查
health_check() {
log_step "执行健康检查..."
sleep 30 # 等待服务启动
log_info "检查基础服务状态..."
remote_exec "
echo '=== 系统服务状态 ==='
systemctl is-active mysqld && echo '✅ MySQL: 运行中' || echo '❌ MySQL: 异常'
systemctl is-active redis && echo '✅ Redis: 运行中' || echo '❌ Redis: 异常'
systemctl is-active nginx && echo '✅ Nginx: 运行中' || echo '❌ Nginx: 异常'
pgrep -f nacos > /dev/null && echo '✅ Nacos: 运行中' || echo '❌ Nacos: 异常'
echo ''
echo '=== Docker服务状态 ==='
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
echo ''
echo '=== 端口监听状态 ==='
netstat -tlnp | grep -E ':(80|3306|6379|8848|9000|9001|9002)' | awk '{print \$1\" \"\$4}' | sort
"
log_info "HTTP接口测试..."
# 测试前端
if remote_exec "curl -s -o /dev/null -w '%{http_code}' http://localhost:80 | grep -q 200"; then
log_success "✅ 前端应用访问正常"
else
log_warn "❌ 前端应用访问异常"
fi
# 测试Nacos
if remote_exec "curl -s -o /dev/null -w '%{http_code}' http://localhost:8848/nacos | grep -q 200"; then
log_success "✅ Nacos控制台访问正常"
else
log_warn "❌ Nacos控制台访问异常"
fi
# 测试网关
sleep 10 # 额外等待网关启动
if remote_exec "curl -s -o /dev/null -w '%{http_code}' http://localhost:9000/actuator/health 2>/dev/null | grep -q 200"; then
log_success "✅ API网关访问正常"
else
log_warn "❌ API网关访问异常(可能还在启动中)"
fi
log_success "健康检查完成"
}
# 显示部署结果
show_deployment_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 " 日志目录: ${LOGS_DIR}"
echo ""
echo "🔧 管理命令:"
echo " ssh ${SERVER_USER}@${SERVER_IP}"
echo " docker-compose -f ${BUILDS_DIR}/docker-compose.yml logs -f"
echo " systemctl status mysqld redis nacos nginx"
echo ""
echo "⚠️ 重要提醒:"
echo " 1. 密码信息已保存到服务器 ${CONFIG_FILE} 文件中"
echo " 2. 请及时修改默认密码"
echo " 3. 建议配置防火墙规则"
echo " 4. 定期备份数据库"
echo ""
}
# 显示帮助信息
show_help() {
echo "情绪博物馆阿里云部署脚本"
echo ""
echo "用法: $0 [选项]"
echo ""
echo "选项:"
echo " check - 检查服务器连接和环境"
echo " env - 安装基础环境(Java、Maven、Node.js、Docker"
echo " mysql - 配置MySQL数据库"
echo " redis - 配置Redis服务"
echo " nacos - 安装配置Nacos"
echo " upload - 上传构建产物"
echo " import-db - 导入数据库"
echo " deploy - 部署应用服务"
echo " nginx - 配置Nginx"
echo " health - 健康检查"
echo " passwords - 创建密码记录文件"
echo " all - 完整部署(默认)"
echo " help - 显示此帮助信息"
echo ""
echo "分步骤部署示例:"
echo " $0 check # 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 ""
}
# 主函数入口
main() {
case "${1:-all}" in
"check")
check_server_connection
;;
"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
;;
"help")
show_help
;;
"all")
echo "🚀 开始完整部署情绪博物馆到阿里云服务器..."
echo ""
# 完整部署流程
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
;;
*)
echo "未知选项: $1"
show_help
exit 1
;;
esac
}
# 执行主函数
main "$@"