660 lines
16 KiB
Bash
Executable File
660 lines
16 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# 情绪博物馆阿里云服务器简化部署脚本
|
|
# 分步骤执行,避免超时问题
|
|
|
|
set -e
|
|
|
|
# 颜色定义
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
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"
|
|
CONFIG_FILE="/data/deployment_config.md"
|
|
|
|
# 日志函数
|
|
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"
|
|
}
|
|
|
|
# 远程执行命令
|
|
remote_exec() {
|
|
local command="$1"
|
|
ssh -o StrictHostKeyChecking=no "${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_info "服务器连接正常"
|
|
}
|
|
|
|
# 创建服务器目录结构
|
|
setup_directories() {
|
|
log_step "创建服务器目录结构..."
|
|
|
|
remote_exec "mkdir -p ${PROGRAMS_DIR}/{mysql,redis,nacos,java,maven,nodejs}"
|
|
remote_exec "mkdir -p ${BUILDS_DIR}"
|
|
remote_exec "mkdir -p ${WEB_DIR}"
|
|
remote_exec "mkdir -p /data/logs/{mysql,redis,nacos,docker,nginx}"
|
|
remote_exec "mkdir -p /data/backup"
|
|
|
|
log_info "目录结构创建完成"
|
|
}
|
|
|
|
# 安装基础软件
|
|
install_basic_packages() {
|
|
log_step "安装基础软件包..."
|
|
|
|
remote_exec "yum update -y && yum install -y wget curl git unzip vim net-tools"
|
|
|
|
log_info "基础软件包安装完成"
|
|
}
|
|
|
|
# 安装Docker
|
|
install_docker() {
|
|
log_step "安装Docker..."
|
|
|
|
remote_exec "
|
|
if ! command -v docker &> /dev/null; then
|
|
curl -fsSL https://get.docker.com | sh
|
|
systemctl start docker
|
|
systemctl enable docker
|
|
echo 'Docker安装完成'
|
|
else
|
|
echo 'Docker已安装'
|
|
fi
|
|
"
|
|
|
|
log_info "Docker安装检查完成"
|
|
}
|
|
|
|
# 安装Java
|
|
install_java() {
|
|
log_step "安装Java 17..."
|
|
|
|
remote_exec "
|
|
if ! java -version 2>&1 | grep -q '17'; then
|
|
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
|
|
"
|
|
|
|
log_info "Java安装检查完成"
|
|
}
|
|
|
|
# 安装Node.js
|
|
install_nodejs() {
|
|
log_step "安装Node.js..."
|
|
|
|
remote_exec "
|
|
if ! command -v node &> /dev/null; then
|
|
curl -fsSL https://rpm.nodesource.com/setup_18.x | bash -
|
|
yum install -y nodejs
|
|
npm config set registry https://registry.npmmirror.com
|
|
echo 'Node.js安装完成'
|
|
else
|
|
echo 'Node.js已安装'
|
|
fi
|
|
"
|
|
|
|
log_info "Node.js安装检查完成"
|
|
}
|
|
|
|
# 安装和配置MySQL
|
|
setup_mysql() {
|
|
log_step "配置MySQL..."
|
|
|
|
# 检查MySQL是否已运行
|
|
if remote_exec "systemctl is-active --quiet mysqld 2>/dev/null && mysql -u root -p${MYSQL_ROOT_PASSWORD} -e 'SELECT 1;' &>/dev/null"; then
|
|
log_info "MySQL已配置且运行正常"
|
|
return 0
|
|
fi
|
|
|
|
log_info "配置MySQL数据库..."
|
|
remote_exec "
|
|
# 测试连接
|
|
if mysql -u root -p${MYSQL_ROOT_PASSWORD} -e 'SELECT 1;' &>/dev/null; then
|
|
echo 'MySQL连接正常'
|
|
|
|
# 创建应用数据库
|
|
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;
|
|
\"
|
|
echo 'MySQL数据库和用户创建完成'
|
|
else
|
|
echo 'MySQL连接失败,请检查密码或安装状态'
|
|
exit 1
|
|
fi
|
|
"
|
|
|
|
log_info "MySQL配置完成"
|
|
}
|
|
|
|
# 安装和配置Redis
|
|
setup_redis() {
|
|
log_step "配置Redis..."
|
|
|
|
if remote_exec "systemctl is-active --quiet redis 2>/dev/null"; then
|
|
log_info "Redis已运行"
|
|
return 0
|
|
fi
|
|
|
|
remote_exec "
|
|
# 安装Redis
|
|
if ! command -v redis-server &> /dev/null; then
|
|
yum install -y epel-release
|
|
yum install -y redis
|
|
fi
|
|
|
|
# 基本配置
|
|
sed -i 's/^bind 127.0.0.1/bind 0.0.0.0/' /etc/redis.conf
|
|
|
|
# 启动服务
|
|
systemctl start redis
|
|
systemctl enable redis
|
|
|
|
echo 'Redis配置完成'
|
|
"
|
|
|
|
log_info "Redis配置完成"
|
|
}
|
|
|
|
# 安装Nacos
|
|
setup_nacos() {
|
|
log_step "配置Nacos..."
|
|
|
|
if remote_exec "pgrep -f nacos > /dev/null"; then
|
|
log_info "Nacos已运行"
|
|
return 0
|
|
fi
|
|
|
|
remote_exec "
|
|
NACOS_DIR='${PROGRAMS_DIR}/nacos'
|
|
|
|
if [ ! -d \"\${NACOS_DIR}\" ]; then
|
|
cd /tmp
|
|
if [ ! -f nacos-server-2.2.0.tar.gz ]; then
|
|
wget https://github.com/alibaba/nacos/releases/download/2.2.0/nacos-server-2.2.0.tar.gz
|
|
fi
|
|
tar -xzf nacos-server-2.2.0.tar.gz
|
|
mv nacos \${NACOS_DIR}
|
|
|
|
# 配置单机模式
|
|
cd \${NACOS_DIR}/conf
|
|
cp application.properties application.properties.backup
|
|
|
|
cat > application.properties << 'EOF'
|
|
server.servlet.contextPath=/nacos
|
|
server.port=8848
|
|
nacos.security.ignore.urls=/,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-ui/public/**,/v1/auth/**,/v1/console/health/**,/actuator/**,/v1/console/server/**
|
|
EOF
|
|
fi
|
|
|
|
# 启动Nacos
|
|
cd \${NACOS_DIR}/bin
|
|
bash startup.sh -m standalone
|
|
|
|
echo 'Nacos配置完成'
|
|
"
|
|
|
|
log_info "Nacos配置完成"
|
|
}
|
|
|
|
# 上传构建产物
|
|
upload_artifacts() {
|
|
log_step "上传构建产物..."
|
|
|
|
# 检查构建产物是否存在
|
|
if [ ! -d "build-output" ]; then
|
|
log_error "构建产物不存在,请先运行: ./deploy-aliyun.sh build"
|
|
exit 1
|
|
fi
|
|
|
|
# 上传JAR文件
|
|
if [ -d "build-output/jars" ]; then
|
|
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
|
|
remote_exec "rm -rf ${WEB_DIR}/*"
|
|
for file in build-output/web/*; do
|
|
if [ -e "$file" ]; then
|
|
remote_copy "$file" "${WEB_DIR}/"
|
|
fi
|
|
done
|
|
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_info "构建产物上传完成"
|
|
}
|
|
|
|
# 导入数据库
|
|
import_database() {
|
|
log_step "导入数据库..."
|
|
|
|
remote_exec "
|
|
if [ -f /tmp/mysql_emotion_museum_final.sql ]; then
|
|
mysql -u root -p${MYSQL_ROOT_PASSWORD} emotion_museum < /tmp/mysql_emotion_museum_final.sql
|
|
echo '数据库导入完成'
|
|
else
|
|
echo '数据库脚本不存在'
|
|
exit 1
|
|
fi
|
|
"
|
|
|
|
log_info "数据库导入完成"
|
|
}
|
|
|
|
# 创建Docker配置
|
|
create_docker_config() {
|
|
log_step "创建Docker配置..."
|
|
|
|
# 创建应用Docker Compose文件
|
|
cat > /tmp/docker-compose-app.yml << 'EOF'
|
|
version: '3.8'
|
|
|
|
services:
|
|
# 网关服务
|
|
gateway:
|
|
image: openjdk:17-jre-slim
|
|
container_name: emotion-gateway
|
|
restart: always
|
|
ports:
|
|
- "9000:9000"
|
|
environment:
|
|
SPRING_PROFILES_ACTIVE: prod
|
|
TZ: Asia/Shanghai
|
|
volumes:
|
|
- /data/builds/emotion-gateway-1.0.0.jar:/app/app.jar
|
|
- /data/logs/docker/gateway:/app/logs
|
|
working_dir: /app
|
|
command: ["java", "-jar", "app.jar"]
|
|
extra_hosts:
|
|
- "host.docker.internal:host-gateway"
|
|
networks:
|
|
- emotion-network
|
|
|
|
# AI服务
|
|
ai-service:
|
|
image: openjdk:17-jre-slim
|
|
container_name: emotion-ai
|
|
restart: always
|
|
ports:
|
|
- "9002:9002"
|
|
environment:
|
|
SPRING_PROFILES_ACTIVE: prod
|
|
TZ: Asia/Shanghai
|
|
volumes:
|
|
- /data/builds/emotion-ai-1.0.0.jar:/app/app.jar
|
|
- /data/logs/docker/ai:/app/logs
|
|
working_dir: /app
|
|
command: ["java", "-jar", "app.jar"]
|
|
extra_hosts:
|
|
- "host.docker.internal:host-gateway"
|
|
networks:
|
|
- emotion-network
|
|
|
|
# 用户服务
|
|
user-service:
|
|
image: openjdk:17-jre-slim
|
|
container_name: emotion-user
|
|
restart: always
|
|
ports:
|
|
- "9001:9001"
|
|
environment:
|
|
SPRING_PROFILES_ACTIVE: prod
|
|
TZ: Asia/Shanghai
|
|
volumes:
|
|
- /data/builds/emotion-user-1.0.0.jar:/app/app.jar
|
|
- /data/logs/docker/user:/app/logs
|
|
working_dir: /app
|
|
command: ["java", "-jar", "app.jar"]
|
|
extra_hosts:
|
|
- "host.docker.internal:host-gateway"
|
|
networks:
|
|
- emotion-network
|
|
|
|
networks:
|
|
emotion-network:
|
|
driver: bridge
|
|
EOF
|
|
|
|
# 上传配置文件
|
|
remote_copy "/tmp/docker-compose-app.yml" "${BUILDS_DIR}/docker-compose.yml"
|
|
rm /tmp/docker-compose-app.yml
|
|
|
|
log_info "Docker配置创建完成"
|
|
}
|
|
|
|
# 配置Nginx
|
|
setup_nginx() {
|
|
log_step "配置Nginx..."
|
|
|
|
remote_exec "
|
|
# 安装Nginx
|
|
if ! command -v nginx &> /dev/null; then
|
|
yum install -y nginx
|
|
fi
|
|
|
|
# 创建配置文件
|
|
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 ${SERVER_IP};
|
|
root ${WEB_DIR};
|
|
index index.html;
|
|
|
|
# 前端路由
|
|
location / {
|
|
try_files \$uri \$uri/ /index.html;
|
|
}
|
|
|
|
# API代理
|
|
location /api/ {
|
|
proxy_pass http://127.0.0.1:9000/;
|
|
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;
|
|
}
|
|
|
|
# 静态资源缓存
|
|
location ~* \\.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
|
|
expires 1y;
|
|
add_header Cache-Control \"public, no-transform\";
|
|
}
|
|
}
|
|
}
|
|
NGINX_EOF
|
|
|
|
# 启动Nginx
|
|
systemctl start nginx
|
|
systemctl enable nginx
|
|
|
|
echo 'Nginx配置完成'
|
|
"
|
|
|
|
log_info "Nginx配置完成"
|
|
}
|
|
|
|
# 启动应用服务
|
|
start_app_services() {
|
|
log_step "启动应用服务..."
|
|
|
|
remote_exec "
|
|
cd ${BUILDS_DIR}
|
|
|
|
# 安装Docker Compose(如果没有)
|
|
if ! command -v docker-compose &> /dev/null; then
|
|
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
|
|
fi
|
|
|
|
# 启动应用服务
|
|
docker-compose up -d
|
|
|
|
echo '应用服务启动完成'
|
|
"
|
|
|
|
log_info "应用服务启动完成"
|
|
}
|
|
|
|
# 健康检查
|
|
health_check() {
|
|
log_step "执行健康检查..."
|
|
|
|
sleep 30 # 等待服务启动
|
|
|
|
log_info "检查基础服务..."
|
|
remote_exec "systemctl is-active mysqld redis nginx || true"
|
|
|
|
log_info "检查Nacos服务..."
|
|
remote_exec "pgrep -f nacos || echo 'Nacos未运行'"
|
|
|
|
log_info "检查Docker服务..."
|
|
remote_exec "docker ps"
|
|
|
|
log_info "检查端口监听..."
|
|
remote_exec "netstat -tlnp | grep -E ':(80|3306|6379|8848|9000|9001|9002)' || true"
|
|
|
|
# HTTP健康检查
|
|
log_info "HTTP接口测试..."
|
|
if remote_exec "curl -s -o /dev/null -w '%{http_code}' http://localhost:80 | grep -q 200"; then
|
|
log_info "✅ 前端应用正常"
|
|
else
|
|
log_warn "❌ 前端应用异常"
|
|
fi
|
|
|
|
if remote_exec "curl -s -o /dev/null -w '%{http_code}' http://localhost:8848/nacos | grep -q 200"; then
|
|
log_info "✅ Nacos控制台正常"
|
|
else
|
|
log_warn "❌ Nacos控制台异常"
|
|
fi
|
|
|
|
log_info "健康检查完成"
|
|
}
|
|
|
|
# 创建配置记录
|
|
create_config_record() {
|
|
log_step "创建配置记录..."
|
|
|
|
cat > /tmp/deployment_config.md << EOF
|
|
# 情绪博物馆部署配置记录
|
|
|
|
## 服务器信息
|
|
- 服务器IP: ${SERVER_IP}
|
|
- 部署时间: $(date '+%Y-%m-%d %H:%M:%S')
|
|
|
|
## 服务配置
|
|
### 数据库
|
|
- MySQL端口: 3306
|
|
- root密码: ${MYSQL_ROOT_PASSWORD}
|
|
- 应用数据库: emotion_museum
|
|
- 应用用户: emotion/EmotionDB2024!
|
|
|
|
### 服务端口
|
|
- Redis: 6379
|
|
- Nacos: 8848
|
|
- 网关: 9000
|
|
- 用户服务: 9001
|
|
- AI服务: 9002
|
|
- Nginx: 80
|
|
|
|
## 访问地址
|
|
- 前端应用: http://${SERVER_IP}
|
|
- API网关: http://${SERVER_IP}:9000
|
|
- Nacos控制台: http://${SERVER_IP}:8848/nacos (nacos/nacos)
|
|
|
|
## 管理命令
|
|
\`\`\`bash
|
|
# 查看服务状态
|
|
systemctl status mysqld redis nginx
|
|
docker ps
|
|
|
|
# 查看应用日志
|
|
docker logs -f emotion-gateway
|
|
docker logs -f emotion-ai
|
|
docker logs -f emotion-user
|
|
|
|
# 重启服务
|
|
systemctl restart mysqld redis 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}
|
|
- 构建目录: ${BUILDS_DIR}
|
|
- 前端目录: ${WEB_DIR}
|
|
- 日志目录: /data/logs
|
|
- 备份目录: /data/backup
|
|
EOF
|
|
|
|
remote_copy "/tmp/deployment_config.md" "${CONFIG_FILE}"
|
|
rm /tmp/deployment_config.md
|
|
|
|
log_info "配置记录已创建: ${CONFIG_FILE}"
|
|
}
|
|
|
|
# 显示部署结果
|
|
show_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 ""
|
|
echo "🔧 管理命令:"
|
|
echo " ssh ${SERVER_USER}@${SERVER_IP}"
|
|
echo " docker-compose -f ${BUILDS_DIR}/docker-compose.yml logs -f"
|
|
echo ""
|
|
}
|
|
|
|
# 主部署流程
|
|
main() {
|
|
echo "🚀 开始部署情绪博物馆到阿里云服务器..."
|
|
echo ""
|
|
|
|
check_server_connection
|
|
setup_directories
|
|
install_basic_packages
|
|
install_docker
|
|
install_java
|
|
install_nodejs
|
|
setup_mysql
|
|
setup_redis
|
|
setup_nacos
|
|
upload_artifacts
|
|
import_database
|
|
create_docker_config
|
|
setup_nginx
|
|
start_app_services
|
|
create_config_record
|
|
health_check
|
|
show_result
|
|
}
|
|
|
|
# 命令行参数处理
|
|
case "${1:-}" in
|
|
"env")
|
|
log_info "仅安装环境..."
|
|
check_server_connection
|
|
setup_directories
|
|
install_basic_packages
|
|
install_docker
|
|
install_java
|
|
install_nodejs
|
|
setup_mysql
|
|
setup_redis
|
|
setup_nacos
|
|
;;
|
|
"app")
|
|
log_info "仅部署应用..."
|
|
check_server_connection
|
|
upload_artifacts
|
|
import_database
|
|
create_docker_config
|
|
setup_nginx
|
|
start_app_services
|
|
health_check
|
|
;;
|
|
"health")
|
|
check_server_connection
|
|
health_check
|
|
;;
|
|
*)
|
|
main
|
|
;;
|
|
esac |