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

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