chore: 更新应用配置和数据库迁移脚本
- 更新 application-dev/test/prod.yml 环境配置 - 更新 V35 清理旧套餐表的迁移脚本 - 添加部署相关文档和脚本 - 移除 CLEAN_V10_FAILED.sql 临时文件
This commit is contained in:
parent
abfbe35d3a
commit
9d76e178de
36
.env.prod.template
Normal file
36
.env.prod.template
Normal file
@ -0,0 +1,36 @@
|
||||
# 生产环境配置模板
|
||||
# 复制此文件为 .env.prod 并填入实际值
|
||||
|
||||
#==============================
|
||||
# 数据库配置
|
||||
#==============================
|
||||
DB_HOST=localhost
|
||||
DB_PORT=3306
|
||||
DB_USERNAME=reading_platform
|
||||
DB_PASSWORD=你的数据库密码
|
||||
|
||||
#==============================
|
||||
# Redis 配置
|
||||
#==============================
|
||||
REDIS_HOST=localhost
|
||||
REDIS_PORT=6379
|
||||
REDIS_PASSWORD=
|
||||
|
||||
#==============================
|
||||
# JWT 配置(生产环境必须修改)
|
||||
#==============================
|
||||
JWT_SECRET=你的-production-jwt-secret-至少-32-字符
|
||||
JWT_EXPIRATION=86400000
|
||||
|
||||
#==============================
|
||||
# 阿里云 OSS 配置
|
||||
#==============================
|
||||
OSS_ENDPOINT=oss-cn-shenzhen.aliyuncs.com
|
||||
OSS_ACCESS_KEY_ID=LTAI5tKZhPofbThbSzDSiWoK
|
||||
OSS_ACCESS_KEY_SECRET=FtcsC7oQX3T0NaChaa9FYq2aoysQFM
|
||||
OSS_BUCKET_NAME=lesingle-kid-course
|
||||
|
||||
#==============================
|
||||
# 服务器配置
|
||||
#==============================
|
||||
SERVER_PORT=8480
|
||||
310
DEPLOY_BAOTA.md
Normal file
310
DEPLOY_BAOTA.md
Normal file
@ -0,0 +1,310 @@
|
||||
# 宝塔面板部署指南
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 方式一:使用部署脚本(推荐)
|
||||
|
||||
```bash
|
||||
# 1. 配置环境变量
|
||||
export REMOTE_HOST=你的服务器 IP
|
||||
export REMOTE_USER=root
|
||||
|
||||
# 2. 部署后端
|
||||
./deploy-backend.sh
|
||||
|
||||
# 3. 部署前端
|
||||
./deploy-frontend.sh
|
||||
```
|
||||
|
||||
### 方式二:手动部署
|
||||
|
||||
---
|
||||
|
||||
## 第一步:在宝塔安装基础服务
|
||||
|
||||
1. 登录宝塔面板(`http://你的IP:8888`)
|
||||
2. 安装 LNMP 套件:
|
||||
- Nginx 1.24+
|
||||
- MySQL 8.0+
|
||||
- PHP 纯静态(前端不需要 PHP)
|
||||
- Redis 7.x
|
||||
|
||||
3. 安装 JDK 17:
|
||||
- 软件商店 → 搜索 "Java"
|
||||
- 安装 JDK 17 版本
|
||||
|
||||
---
|
||||
|
||||
## 第二步:创建数据库
|
||||
|
||||
1. 宝塔面板 → 数据库 → 添加
|
||||
2. 填写信息:
|
||||
- 数据库名:`lesingle-edu-reading-platform`
|
||||
- 用户名:`reading_platform`
|
||||
- 密码:设置一个强密码(保存好)
|
||||
- 权限:全部
|
||||
|
||||
3. 记录数据库信息,后面要用
|
||||
|
||||
---
|
||||
|
||||
## 第三步:部署后端
|
||||
|
||||
### 3.1 上传 JAR 包
|
||||
|
||||
```bash
|
||||
# 本地构建
|
||||
cd /f/LesingleProject/lesingle-kindergarten-course/kindergarten_java/reading-platform-java
|
||||
mvn clean package -DskipTests
|
||||
|
||||
# 上传到服务器
|
||||
scp target/reading-platform-1.0.0.jar root@你的 IP:/www/wwwroot/reading-platform/app.jar
|
||||
```
|
||||
|
||||
### 3.2 创建启动脚本
|
||||
|
||||
在服务器上创建 `/www/wwwroot/reading-platform/start.sh`:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
export SPRING_PROFILES_ACTIVE=prod
|
||||
export SERVER_PORT=8480
|
||||
export DB_HOST=localhost
|
||||
export DB_PASSWORD=你的数据库密码
|
||||
export JWT_SECRET=你的 JWT 密钥
|
||||
|
||||
nohup java -jar -Xms512m -Xmx1024m /www/wwwroot/reading-platform/app.jar \
|
||||
--spring.profiles.active=prod > /www/wwwroot/reading-platform/logs/app.log 2>&1 &
|
||||
echo $! > /www/wwwroot/reading-platform/app.pid
|
||||
```
|
||||
|
||||
```bash
|
||||
chmod +x /www/wwwroot/reading-platform/start.sh
|
||||
```
|
||||
|
||||
### 3.3 创建环境变量文件
|
||||
|
||||
`/www/wwwroot/reading-platform/.env`:
|
||||
|
||||
```bash
|
||||
# 数据库
|
||||
DB_HOST=localhost
|
||||
DB_PASSWORD=你的数据库密码
|
||||
|
||||
# JWT
|
||||
JWT_SECRET=你的-production-jwt-secret-至少-32-字符
|
||||
JWT_EXPIRATION=86400000
|
||||
|
||||
# Redis
|
||||
REDIS_HOST=localhost
|
||||
REDIS_PORT=6379
|
||||
|
||||
# OSS
|
||||
OSS_ACCESS_KEY_ID=LTAI5tKZhPofbThbSzDSiWoK
|
||||
OSS_ACCESS_KEY_SECRET=FtcsC7oQX3T0NaChaa9FYq2aoysQFM
|
||||
OSS_BUCKET_NAME=lesingle-kid-course
|
||||
```
|
||||
|
||||
### 3.4 启动后端
|
||||
|
||||
```bash
|
||||
cd /www/wwwroot/reading-platform
|
||||
./start.sh
|
||||
|
||||
# 查看日志
|
||||
tail -f logs/app.log
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 第四步:部署前端
|
||||
|
||||
### 4.1 本地构建
|
||||
|
||||
```bash
|
||||
cd /f/LesingleProject/lesingle-kindergarten-course/kindergarten_java/reading-platform-frontend
|
||||
npm run build
|
||||
```
|
||||
|
||||
### 4.2 上传到服务器
|
||||
|
||||
```bash
|
||||
# 上传到宝塔站点目录
|
||||
scp -r dist/* root@你的 IP:/www/wwwroot/你的域名/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 第五步:配置 Nginx 反向代理
|
||||
|
||||
1. 宝塔面板 → 网站 → 添加站点
|
||||
2. 填写域名,根目录设为 `/www/wwwroot/你的域名`
|
||||
3. 确定后,点击网站 → 设置 → 配置文件
|
||||
4. 添加以下配置:
|
||||
|
||||
```nginx
|
||||
# 前端页面
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# 后端 API 反向代理
|
||||
location /api {
|
||||
proxy_pass http://localhost:8480;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
}
|
||||
|
||||
# 文件上传代理
|
||||
location /uploads {
|
||||
proxy_pass http://localhost:8480;
|
||||
}
|
||||
```
|
||||
|
||||
5. 保存配置
|
||||
|
||||
---
|
||||
|
||||
## 第六步:配置防火墙
|
||||
|
||||
1. 宝塔面板 → 安全 → 放行端口
|
||||
2. 放行以下端口:
|
||||
- 80(HTTP)
|
||||
- 443(HTTPS,如果用 SSL)
|
||||
- 8480(后端 API,可选,如果通过 Nginx 代理就不需要)
|
||||
|
||||
---
|
||||
|
||||
## 第七步:验证部署
|
||||
|
||||
```bash
|
||||
# 检查后端健康状态
|
||||
curl http://localhost:8480/actuator/health
|
||||
|
||||
# 访问前端
|
||||
curl http://localhost
|
||||
|
||||
# 测试 API
|
||||
curl http://localhost:8480/api/v1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 第八步:申请 SSL 证书(可选)
|
||||
|
||||
1. 宝塔面板 → 网站 → 点击对应网站 → SSL
|
||||
2. 选择 "Let's Encrypt" 免费证书
|
||||
3. 填写邮箱,点击申请
|
||||
4. 申请成功后,开启"强制 HTTPS"
|
||||
|
||||
---
|
||||
|
||||
## 管理命令
|
||||
|
||||
### 后端管理
|
||||
|
||||
```bash
|
||||
# 启动
|
||||
cd /www/wwwroot/reading-platform && ./start.sh
|
||||
|
||||
# 停止
|
||||
cd /www/wwwroot/reading-platform && ./stop.sh
|
||||
|
||||
# 重启
|
||||
cd /www/wwwroot/reading-platform && ./stop.sh && ./start.sh
|
||||
|
||||
# 查看日志
|
||||
tail -f /www/wwwroot/reading-platform/logs/app.log
|
||||
|
||||
# 查看进程
|
||||
ps aux | grep reading-platform
|
||||
```
|
||||
|
||||
### 前端更新
|
||||
|
||||
```bash
|
||||
# 本地重新构建并上传
|
||||
cd reading-platform-frontend
|
||||
npm run build
|
||||
scp -r dist/* root@你的 IP:/www/wwwroot/你的域名/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 常见问题
|
||||
|
||||
### 1. 后端启动失败
|
||||
|
||||
检查日志:
|
||||
```bash
|
||||
tail -100 /www/wwwroot/reading-platform/logs/app.log
|
||||
```
|
||||
|
||||
常见原因:
|
||||
- JDK 版本不对(必须是 17)
|
||||
- 数据库连接失败
|
||||
- 端口被占用
|
||||
|
||||
### 2. 前端页面空白
|
||||
|
||||
- 检查 Nginx 配置是否正确
|
||||
- 打开浏览器 Console 查看错误
|
||||
- 检查 API 请求是否 404
|
||||
|
||||
### 3. API 请求失败
|
||||
|
||||
- 检查 Nginx 反向代理配置
|
||||
- 确认后端服务是否运行
|
||||
- 检查防火墙端口
|
||||
|
||||
### 4. 文件上传失败
|
||||
|
||||
- 检查 OSS 配置
|
||||
- 检查 Nginx 上传大小限制
|
||||
- 查看后端日志
|
||||
|
||||
---
|
||||
|
||||
## 性能优化
|
||||
|
||||
### JVM 优化参数
|
||||
|
||||
```bash
|
||||
java -jar \
|
||||
-Xms1g \
|
||||
-Xmx2g \
|
||||
-XX:+UseG1GC \
|
||||
-XX:MaxGCPauseMillis=200 \
|
||||
-XX:+HeapDumpOnOutOfMemoryError \
|
||||
app.jar
|
||||
```
|
||||
|
||||
### Nginx 优化
|
||||
|
||||
```nginx
|
||||
# 开启 gzip 压缩
|
||||
gzip on;
|
||||
gzip_types text/plain text/css application/json application/javascript;
|
||||
|
||||
# 上传大小限制
|
||||
client_max_body_size 100M;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 备份与恢复
|
||||
|
||||
### 数据库备份
|
||||
|
||||
```bash
|
||||
# 宝塔面板 → 数据库 → 备份
|
||||
# 或命令行
|
||||
mysqldump -u reading_platform -p lesingle-edu-reading-platform > backup.sql
|
||||
```
|
||||
|
||||
### 文件备份
|
||||
|
||||
```bash
|
||||
tar -czf backup-$(date +%Y%m%d).tar.gz /www/wwwroot/reading-platform
|
||||
```
|
||||
170
README-BAOTA-DEPLOY.md
Normal file
170
README-BAOTA-DEPLOY.md
Normal file
@ -0,0 +1,170 @@
|
||||
# 宝塔部署快速配置指南
|
||||
|
||||
## 第一次部署前,请在宝塔面板完成以下操作:
|
||||
|
||||
### 1. 安装基础服务
|
||||
|
||||
登录宝塔面板 → 软件商店 → 安装以下软件:
|
||||
|
||||
| 软件 | 版本 | 说明 |
|
||||
|------|------|------|
|
||||
| Nginx | 1.24+ | Web 服务器 |
|
||||
| MySQL | 8.0+ | 数据库 |
|
||||
| Redis | 7.x | 缓存 |
|
||||
| Java | JDK 17 | 运行环境 |
|
||||
|
||||
### 2. 创建数据库
|
||||
|
||||
宝塔面板 → 数据库 → 添加:
|
||||
|
||||
```
|
||||
数据库名:lesingle-edu-reading-platform
|
||||
用户名:reading_platform
|
||||
密码:[设置一个强密码,记下来]
|
||||
权限:全部
|
||||
```
|
||||
|
||||
### 3. 配置环境变量
|
||||
|
||||
复制配置文件模板:
|
||||
|
||||
```bash
|
||||
cp .env.prod.template .env.prod
|
||||
```
|
||||
|
||||
编辑 `.env.prod`,填入实际值:
|
||||
|
||||
```bash
|
||||
# 数据库密码(从宝塔获取)
|
||||
DB_PASSWORD=你的数据库密码
|
||||
|
||||
# JWT 密钥(必须修改)
|
||||
JWT_SECRET=你的-production-jwt-secret-至少-32-字符
|
||||
|
||||
# Redis 密码(如果宝塔设置了)
|
||||
REDIS_PASSWORD=
|
||||
```
|
||||
|
||||
### 4. 修改部署脚本配置
|
||||
|
||||
编辑 `deploy-backend.sh`,找到环境变量部分,填入你的配置:
|
||||
|
||||
```bash
|
||||
# 在启动脚本中添加环境变量
|
||||
export DB_PASSWORD=你的数据库密码
|
||||
export JWT_SECRET=你的 JWT 密钥
|
||||
```
|
||||
|
||||
或者在服务器上创建 `/www/wwwroot/reading-platform/.env` 文件。
|
||||
|
||||
---
|
||||
|
||||
## 一键部署
|
||||
|
||||
```bash
|
||||
# 方式 1:使用主部署脚本
|
||||
./deploy.sh root@你的服务器 IP
|
||||
|
||||
# 方式 2:分别部署
|
||||
export REMOTE_HOST=你的服务器 IP
|
||||
./deploy-backend.sh # 部署后端
|
||||
./deploy-frontend.sh # 部署前端
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 部署后配置
|
||||
|
||||
### 1. 配置 Nginx 反向代理
|
||||
|
||||
宝塔面板 → 网站 → 你的网站 → 设置 → 配置文件:
|
||||
|
||||
粘贴 `nginx-baota.conf` 中的配置。
|
||||
|
||||
### 2. 验证部署
|
||||
|
||||
```bash
|
||||
# SSH 登录服务器
|
||||
ssh root@你的服务器 IP
|
||||
|
||||
# 检查后端健康状态
|
||||
curl http://localhost:8480/actuator/health
|
||||
|
||||
# 查看后端日志
|
||||
tail -f /www/wwwroot/reading-platform/logs/app.log
|
||||
```
|
||||
|
||||
### 3. 访问应用
|
||||
|
||||
- 前端:http://你的服务器 IP
|
||||
- API 文档:http://你的服务器 IP:8480/swagger-ui.html
|
||||
|
||||
---
|
||||
|
||||
## 常用命令
|
||||
|
||||
### 后端管理
|
||||
|
||||
```bash
|
||||
# 登录服务器
|
||||
ssh root@你的服务器 IP
|
||||
|
||||
# 进入目录
|
||||
cd /www/wwwroot/reading-platform
|
||||
|
||||
# 启动
|
||||
./start.sh
|
||||
|
||||
# 停止
|
||||
./stop.sh
|
||||
|
||||
# 查看日志
|
||||
tail -f logs/app.log
|
||||
|
||||
# 查看进程
|
||||
ps aux | grep app.jar
|
||||
```
|
||||
|
||||
### 前端更新
|
||||
|
||||
```bash
|
||||
# 本地重新构建并部署
|
||||
./deploy-frontend.sh root@你的服务器 IP
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 问题排查
|
||||
|
||||
### 后端启动失败
|
||||
|
||||
```bash
|
||||
# 查看详细日志
|
||||
tail -100 /www/wwwroot/reading-platform/logs/app.log
|
||||
|
||||
# 检查 Java 版本
|
||||
java -version
|
||||
|
||||
# 检查端口占用
|
||||
netstat -tlnp | grep 8480
|
||||
```
|
||||
|
||||
### 前端页面空白
|
||||
|
||||
1. 打开浏览器 Console(F12)
|
||||
2. 查看 Network 标签,检查 API 请求
|
||||
3. 确认 Nginx 反向代理配置正确
|
||||
|
||||
### 数据库连接失败
|
||||
|
||||
1. 确认数据库已创建
|
||||
2. 确认数据库密码正确
|
||||
3. 确认 MySQL 服务运行中
|
||||
|
||||
---
|
||||
|
||||
## 需要帮助?
|
||||
|
||||
- 详细部署文档:`DEPLOY_BAOTA.md`
|
||||
- Nginx 配置:`nginx-baota.conf`
|
||||
- 环境变量模板:`.env.prod.template`
|
||||
191
deploy-backend.sh
Normal file
191
deploy-backend.sh
Normal file
@ -0,0 +1,191 @@
|
||||
#!/bin/bash
|
||||
|
||||
#===============================================================================
|
||||
# 后端生产环境部署脚本
|
||||
#
|
||||
# 使用方法:
|
||||
# ./deploy-backend.sh user@host
|
||||
# 或
|
||||
# export REMOTE_USER=root
|
||||
# export REMOTE_HOST=8.148.151.56
|
||||
# ./deploy-backend.sh
|
||||
#===============================================================================
|
||||
|
||||
set -e
|
||||
|
||||
# 配置
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
BACKEND_DIR="$SCRIPT_DIR/reading-platform-java"
|
||||
REMOTE_BASE_DIR="/www/wwwroot/reading-platform"
|
||||
|
||||
# SSH 配置
|
||||
REMOTE_USER="${REMOTE_USER:-root}"
|
||||
REMOTE_HOST="${REMOTE_HOST:-}"
|
||||
REMOTE_PORT="${REMOTE_PORT:-22}"
|
||||
|
||||
# 颜色
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
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"; }
|
||||
|
||||
# 检查参数
|
||||
if [ -n "$1" ]; then
|
||||
if [[ "$1" == *"@"* ]]; then
|
||||
REMOTE_USER=$(echo "$1" | cut -d'@' -f1)
|
||||
REMOTE_HOST=$(echo "$1" | cut -d'@' -f2)
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$REMOTE_HOST" ]; then
|
||||
log_error "请提供远程主机:$0 user@host 或设置 REMOTE_HOST 环境变量"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=============================================="
|
||||
echo " 后端部署到宝塔"
|
||||
echo "=============================================="
|
||||
echo ""
|
||||
echo " 远程主机:$REMOTE_USER@$REMOTE_HOST"
|
||||
echo " 部署目录:$REMOTE_BASE_DIR"
|
||||
echo ""
|
||||
|
||||
# 步骤 1: 构建 JAR
|
||||
log_step "构建后端..."
|
||||
cd "$BACKEND_DIR"
|
||||
|
||||
if ! command -v mvn &> /dev/null; then
|
||||
log_error "未找到 Maven"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查 Java 版本
|
||||
java_ver=$(java -version 2>&1 | head -n 1 | cut -d'"' -f2 | cut -d'.' -f1)
|
||||
if [ "$java_ver" != "17" ]; then
|
||||
log_warn "当前 Java 版本:$java_ver,建议使用 JDK 17"
|
||||
fi
|
||||
|
||||
mvn clean package -DskipTests
|
||||
|
||||
JAR_FILE="$BACKEND_DIR/target/reading-platform-1.0.0.jar"
|
||||
if [ ! -f "$JAR_FILE" ]; then
|
||||
log_error "构建失败,未找到 JAR 包"
|
||||
exit 1
|
||||
fi
|
||||
log_info "构建成功:$JAR_FILE"
|
||||
|
||||
# 步骤 2: 上传到服务器
|
||||
log_step "上传到远程服务器..."
|
||||
|
||||
# 创建目录
|
||||
ssh -o StrictHostKeyChecking=no -p "$REMOTE_PORT" "$REMOTE_USER@$REMOTE_HOST" << 'ENDSSH'
|
||||
mkdir -p /www/wwwroot/reading-platform
|
||||
mkdir -p /www/wwwroot/reading-platform/logs
|
||||
ENDSSH
|
||||
|
||||
# 上传 JAR
|
||||
scp -o StrictHostKeyChecking=no -P "$REMOTE_PORT" \
|
||||
"$JAR_FILE" \
|
||||
"$REMOTE_USER@$REMOTE_HOST:$REMOTE_BASE_DIR/app.jar"
|
||||
|
||||
# 步骤 3: 创建启动脚本
|
||||
log_step "创建启动脚本..."
|
||||
|
||||
cat > /tmp/baota-start.sh << 'EOF'
|
||||
#!/bin/bash
|
||||
APP_DIR="/www/wwwroot/reading-platform"
|
||||
JAR_FILE="$APP_DIR/app.jar"
|
||||
PID_FILE="$APP_DIR/app.pid"
|
||||
LOG_FILE="$APP_DIR/logs/application.log"
|
||||
|
||||
# 环境变量
|
||||
export SPRING_PROFILES_ACTIVE=prod
|
||||
export SERVER_PORT=8480
|
||||
|
||||
# 停止旧进程
|
||||
if [ -f "$PID_FILE" ]; then
|
||||
OLD_PID=$(cat "$PID_FILE")
|
||||
if kill -0 "$OLD_PID" 2>/dev/null; then
|
||||
echo "停止旧进程 (PID: $OLD_PID)..."
|
||||
kill "$OLD_PID"
|
||||
sleep 3
|
||||
fi
|
||||
rm -f "$PID_FILE"
|
||||
fi
|
||||
pkill -f "app.jar" 2>/dev/null || true
|
||||
|
||||
# 启动
|
||||
echo "启动应用..."
|
||||
nohup java -jar \
|
||||
-Xms512m \
|
||||
-Xmx1024m \
|
||||
-XX:+UseG1GC \
|
||||
"$JAR_FILE" \
|
||||
--spring.profiles.active=prod \
|
||||
> "$LOG_FILE" 2>&1 &
|
||||
|
||||
NEW_PID=$!
|
||||
echo $NEW_PID > "$PID_FILE"
|
||||
echo "已启动 (PID: $NEW_PID)"
|
||||
|
||||
# 等待启动
|
||||
for i in {1..30}; do
|
||||
if curl -s http://localhost:8480/actuator/health 2>/dev/null; then
|
||||
echo "启动成功!"
|
||||
exit 0
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
echo "启动超时,检查日志:tail -100 $LOG_FILE"
|
||||
exit 1
|
||||
EOF
|
||||
|
||||
scp -o StrictHostKeyChecking=no -P "$REMOTE_PORT" \
|
||||
/tmp/baota-start.sh \
|
||||
"$REMOTE_USER@$REMOTE_HOST:$REMOTE_BASE_DIR/start.sh"
|
||||
|
||||
# 步骤 4: 创建停止脚本
|
||||
cat > /tmp/baota-stop.sh << 'EOF'
|
||||
#!/bin/bash
|
||||
PID_FILE="/www/wwwroot/reading-platform/app.pid"
|
||||
if [ -f "$PID_FILE" ]; then
|
||||
PID=$(cat "$PID_FILE")
|
||||
if kill -0 "$PID" 2>/dev/null; then
|
||||
kill "$PID"
|
||||
echo "已停止 (PID: $PID)"
|
||||
fi
|
||||
rm -f "$PID_FILE"
|
||||
fi
|
||||
pkill -f "app.jar" 2>/dev/null || true
|
||||
echo "已停止"
|
||||
EOF
|
||||
|
||||
scp -o StrictHostKeyChecking=no -P "$REMOTE_PORT" \
|
||||
/tmp/baota-stop.sh \
|
||||
"$REMOTE_USER@$REMOTE_HOST:$REMOTE_BASE_DIR/stop.sh"
|
||||
|
||||
# 设置权限
|
||||
ssh -o StrictHostKeyChecking=no -p "$REMOTE_PORT" "$REMOTE_USER@$REMOTE_HOST" \
|
||||
"chmod +x $REMOTE_BASE_DIR/start.sh $REMOTE_BASE_DIR/stop.sh"
|
||||
|
||||
log_info "部署完成"
|
||||
|
||||
echo ""
|
||||
echo "=============================================="
|
||||
echo " 后端部署完成!"
|
||||
echo "=============================================="
|
||||
echo ""
|
||||
echo " 远程登录:ssh $REMOTE_USER@$REMOTE_HOST"
|
||||
echo " 启动服务:cd $REMOTE_BASE_DIR && ./start.sh"
|
||||
echo " 停止服务:cd $REMOTE_BASE_DIR && ./stop.sh"
|
||||
echo " 查看日志:tail -f $REMOTE_BASE_DIR/logs/application.log"
|
||||
echo ""
|
||||
echo " 健康检查:curl http://localhost:8480/actuator/health"
|
||||
echo ""
|
||||
120
deploy-frontend.sh
Normal file
120
deploy-frontend.sh
Normal file
@ -0,0 +1,120 @@
|
||||
#!/bin/bash
|
||||
|
||||
#===============================================================================
|
||||
# 前端生产环境构建并部署脚本
|
||||
#
|
||||
# 使用方法:
|
||||
# ./deploy-frontend.sh user@host
|
||||
# 或
|
||||
# export REMOTE_USER=root
|
||||
# export REMOTE_HOST=8.148.151.56
|
||||
# ./deploy-frontend.sh
|
||||
#===============================================================================
|
||||
|
||||
set -e
|
||||
|
||||
# 配置
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
FRONTEND_DIR="$SCRIPT_DIR/reading-platform-frontend"
|
||||
REMOTE_DIR="/www/wwwroot/reading.ycapp.cn"
|
||||
|
||||
# SSH 配置(可通过环境变量覆盖)
|
||||
REMOTE_USER="${REMOTE_USER:-root}"
|
||||
REMOTE_HOST="${REMOTE_HOST:-}"
|
||||
REMOTE_PORT="${REMOTE_PORT:-22}"
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
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"; }
|
||||
|
||||
# 检查参数
|
||||
if [ -n "$1" ]; then
|
||||
if [[ "$1" == *"@"* ]]; then
|
||||
REMOTE_USER=$(echo "$1" | cut -d'@' -f1)
|
||||
REMOTE_HOST=$(echo "$1" | cut -d'@' -f2)
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$REMOTE_HOST" ]; then
|
||||
log_error "请提供远程主机:$0 user@host 或设置 REMOTE_HOST 环境变量"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=============================================="
|
||||
echo " 前端部署到宝塔"
|
||||
echo "=============================================="
|
||||
echo ""
|
||||
echo " 远程主机:$REMOTE_USER@$REMOTE_HOST"
|
||||
echo " 部署目录:$REMOTE_DIR"
|
||||
echo ""
|
||||
|
||||
cd "$FRONTEND_DIR"
|
||||
|
||||
# 步骤 1: 检查 Node.js
|
||||
log_step "检查环境..."
|
||||
if ! command -v node &> /dev/null; then
|
||||
log_error "未找到 Node.js"
|
||||
exit 1
|
||||
fi
|
||||
node_version=$(node -v)
|
||||
npm_version=$(npm -v)
|
||||
log_info "Node.js: $node_version, npm: $npm_version"
|
||||
|
||||
# 步骤 2: 安装依赖
|
||||
log_step "安装依赖..."
|
||||
if [ ! -d "node_modules" ]; then
|
||||
npm install
|
||||
else
|
||||
log_info "node_modules 已存在,跳过依赖安装"
|
||||
fi
|
||||
|
||||
# 步骤 3: 构建
|
||||
log_step "构建前端..."
|
||||
npm run build
|
||||
|
||||
if [ ! -d "dist" ]; then
|
||||
log_error "构建失败,未找到 dist 目录"
|
||||
exit 1
|
||||
fi
|
||||
log_info "构建成功"
|
||||
|
||||
# 步骤 4: 上传到服务器
|
||||
log_step "上传到远程服务器..."
|
||||
|
||||
# 创建远程目录
|
||||
ssh -o StrictHostKeyChecking=no -p "$REMOTE_PORT" "$REMOTE_USER@$REMOTE_HOST" \
|
||||
"mkdir -p $REMOTE_DIR"
|
||||
|
||||
# 上传文件
|
||||
scp -o StrictHostKeyChecking=no -r -P "$REMOTE_PORT" \
|
||||
dist/ \
|
||||
"$REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR/"
|
||||
|
||||
log_info "上传完成"
|
||||
|
||||
# 步骤 5: 设置权限
|
||||
log_step "设置文件权限..."
|
||||
ssh -o StrictHostKeyChecking=no -p "$REMOTE_PORT" "$REMOTE_USER@$REMOTE_HOST" << 'ENDSSH'
|
||||
chown -R www:www /www/wwwroot/reading.ycapp.cn
|
||||
chmod -R 755 /www/wwwroot/reading.ycapp.cn
|
||||
ENDSSH
|
||||
|
||||
echo ""
|
||||
echo "=============================================="
|
||||
echo " 前端部署完成!"
|
||||
echo "=============================================="
|
||||
echo ""
|
||||
echo " 访问地址:http://${REMOTE_HOST}"
|
||||
echo ""
|
||||
echo " 下一步:在宝塔面板配置 Nginx 反向代理"
|
||||
echo " /api -> http://localhost:8480"
|
||||
echo ""
|
||||
408
deploy-to-baota.sh
Normal file
408
deploy-to-baota.sh
Normal file
@ -0,0 +1,408 @@
|
||||
#!/bin/bash
|
||||
|
||||
#===============================================================================
|
||||
# 幼儿阅读教学服务平台 - 一键部署到宝塔面板
|
||||
#
|
||||
# 使用前请配置:
|
||||
# 1. 远程服务器信息(IP、用户名、密码/密钥)
|
||||
# 2. 宝塔面板信息(面板地址、API 密钥)
|
||||
# 3. 数据库信息
|
||||
#===============================================================================
|
||||
|
||||
set -e
|
||||
|
||||
#============================== 配置区域 ==============================
|
||||
|
||||
# 远程服务器配置
|
||||
REMOTE_HOST="8.148.151.56" # 服务器 IP
|
||||
REMOTE_USER="root" # SSH 用户名
|
||||
REMOTE_PORT="22" # SSH 端口
|
||||
# 推荐使用 SSH 密钥,如无密钥将使用密码认证
|
||||
REMOTE_PASSWORD="" # SSH 密码(可选)
|
||||
SSH_KEY_FILE="~/.ssh/id_rsa" # SSH 密钥文件
|
||||
|
||||
# 部署路径配置
|
||||
REMOTE_BASE_DIR="/www/wwwroot/reading-platform" # 后端部署目录
|
||||
REMOTE_FRONTEND_DIR="/www/wwwroot/reading.ycapp.cn" # 前端部署目录(宝塔站点目录)
|
||||
|
||||
# 宝塔面板配置
|
||||
BAOTA_PANEL_URL="http://${REMOTE_HOST}:8888" # 宝塔面板地址
|
||||
BAOTA_API_KEY="" # 宝塔 API 密钥(在宝塔面板 → 设置 → API 获取)
|
||||
BAOTA_SECRET_KEY="" # 宝塔 API 密钥
|
||||
|
||||
# 数据库配置(宝塔中创建的数据库)
|
||||
DB_HOST="localhost"
|
||||
DB_PORT="3306"
|
||||
DB_NAME="lesingle-edu-reading-platform"
|
||||
DB_USER="reading_platform"
|
||||
DB_PASSWORD="" # 数据库密码
|
||||
|
||||
# JWT 配置(生产环境必须修改)
|
||||
JWT_SECRET="your-production-jwt-secret-change-this"
|
||||
JWT_EXPIRATION="86400000"
|
||||
|
||||
# Redis 配置
|
||||
REDIS_HOST="localhost"
|
||||
REDIS_PORT="6379"
|
||||
REDIS_PASSWORD=""
|
||||
|
||||
# OSS 配置(生产环境)
|
||||
OSS_ACCESS_KEY_ID="LTAI5tKZhPofbThbSzDSiWoK"
|
||||
OSS_ACCESS_KEY_SECRET="FtcsC7oQX3T0NaChaa9FYq2aoysQFM"
|
||||
OSS_BUCKET_NAME="lesingle-kid-course"
|
||||
OSS_ENDPOINT="oss-cn-shenzhen.aliyuncs.com"
|
||||
|
||||
#============================== 脚本主体 ==============================
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# 日志函数
|
||||
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"; }
|
||||
|
||||
# 检查配置
|
||||
check_config() {
|
||||
log_step "检查配置..."
|
||||
|
||||
if [ -z "$REMOTE_HOST" ]; then
|
||||
log_error "请配置 REMOTE_HOST(服务器 IP)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 检查本地是否有 JAR 包
|
||||
JAR_FILE="reading-platform-java/target/reading-platform-1.0.0.jar"
|
||||
if [ ! -f "$JAR_FILE" ]; then
|
||||
log_warn "未找到 JAR 包,将先执行构建..."
|
||||
BUILD_NEEDED=true
|
||||
fi
|
||||
|
||||
# 检查前端是否有 dist
|
||||
if [ ! -d "reading-platform-frontend/dist" ]; then
|
||||
log_warn "未找到前端构建文件,将先执行构建..."
|
||||
BUILD_FRONTEND_NEEDED=true
|
||||
fi
|
||||
}
|
||||
|
||||
# 构建后端
|
||||
build_backend() {
|
||||
if [ "$BUILD_NEEDED" != "true" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
log_step "构建后端服务..."
|
||||
cd "reading-platform-java"
|
||||
|
||||
# 检查 JDK 版本
|
||||
if command -v java &> /dev/null; then
|
||||
JAVA_VERSION=$(java -version 2>&1 | head -n 1 | cut -d'"' -f2 | cut -d'.' -f1)
|
||||
if [ "$JAVA_VERSION" != "17" ]; then
|
||||
log_warn "当前 Java 版本为 $JAVA_VERSION,建议 JDK 17"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Maven 构建
|
||||
if command -v mvn &> /dev/null; then
|
||||
mvn clean package -DskipTests
|
||||
else
|
||||
log_error "未找到 Maven,请先安装"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd ..
|
||||
|
||||
if [ -f "$JAR_FILE" ]; then
|
||||
log_info "后端构建成功:$JAR_FILE"
|
||||
else
|
||||
log_error "后端构建失败"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 构建前端
|
||||
build_frontend() {
|
||||
if [ "$BUILD_FRONTEND_NEEDED" != "true" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
log_step "构建前端..."
|
||||
cd "reading-platform-frontend"
|
||||
|
||||
# 检查 Node.js
|
||||
if ! command -v node &> /dev/null; then
|
||||
log_error "未找到 Node.js,请先安装"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 安装依赖(如果 node_modules 不存在)
|
||||
if [ ! -d "node_modules" ]; then
|
||||
log_info "安装前端依赖..."
|
||||
npm install
|
||||
fi
|
||||
|
||||
# 构建
|
||||
npm run build
|
||||
|
||||
cd ..
|
||||
|
||||
if [ -d "reading-platform-frontend/dist" ]; then
|
||||
log_info "前端构建成功"
|
||||
else
|
||||
log_error "前端构建失败"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# SSH 上传文件
|
||||
upload_files() {
|
||||
log_step "上传文件到远程服务器..."
|
||||
|
||||
# 创建 SSH 命令别名(根据是否有密码)
|
||||
if [ -n "$REMOTE_PASSWORD" ]; then
|
||||
SSH_PASS="sshpass -p '$REMOTE_PASSWORD'"
|
||||
SCP_PASS="sshpass -p '$REMOTE_PASSWORD'"
|
||||
else
|
||||
SSH_PASS=""
|
||||
SCP_PASS=""
|
||||
fi
|
||||
|
||||
# 测试 SSH 连接
|
||||
log_info "测试 SSH 连接..."
|
||||
if ! ssh -o StrictHostKeyChecking=no -p "$REMOTE_PORT" "$REMOTE_USER@$REMOTE_HOST" "echo '连接成功'" 2>/dev/null; then
|
||||
log_error "SSH 连接失败,请检查服务器配置"
|
||||
exit 1
|
||||
fi
|
||||
log_info "SSH 连接成功"
|
||||
|
||||
# 创建远程目录
|
||||
log_info "创建远程目录..."
|
||||
ssh -o StrictHostKeyChecking=no -p "$REMOTE_PORT" "$REMOTE_USER@$REMOTE_HOST" << 'ENDSSH'
|
||||
mkdir -p /www/wwwroot/reading-platform
|
||||
mkdir -p /www/wwwroot/reading-platform/logs
|
||||
ENDSSH
|
||||
|
||||
# 上传 JAR 包
|
||||
log_info "上传后端 JAR 包..."
|
||||
scp -o StrictHostKeyChecking=no -P "$REMOTE_PORT" \
|
||||
"reading-platform-java/target/reading-platform-1.0.0.jar" \
|
||||
"$REMOTE_USER@$REMOTE_HOST:/www/wwwroot/reading-platform/app.jar"
|
||||
|
||||
# 上传启动脚本
|
||||
log_info "上传启动脚本..."
|
||||
cat > /tmp/deploy-start.sh << 'EOF'
|
||||
#!/bin/bash
|
||||
# 阅读平台后端启动脚本
|
||||
|
||||
APP_DIR="/www/wwwroot/reading-platform"
|
||||
JAR_FILE="$APP_DIR/app.jar"
|
||||
PID_FILE="$APP_DIR/app.pid"
|
||||
LOG_FILE="$APP_DIR/logs/application.log"
|
||||
|
||||
# 环境变量
|
||||
export SPRING_PROFILES_ACTIVE=prod
|
||||
export SERVER_PORT=8480
|
||||
export DB_HOST=${DB_HOST:-localhost}
|
||||
export DB_PASSWORD=${DB_PASSWORD}
|
||||
export JWT_SECRET=${JWT_SECRET}
|
||||
|
||||
# 检查是否已在运行
|
||||
if [ -f "$PID_FILE" ]; then
|
||||
OLD_PID=$(cat "$PID_FILE")
|
||||
if kill -0 "$OLD_PID" 2>/dev/null; then
|
||||
echo "停止旧进程 (PID: $OLD_PID)..."
|
||||
kill "$OLD_PID"
|
||||
sleep 3
|
||||
fi
|
||||
rm -f "$PID_FILE"
|
||||
fi
|
||||
|
||||
# 启动应用
|
||||
echo "启动阅读平台后端..."
|
||||
nohup java -jar \
|
||||
-Xms512m \
|
||||
-Xmx1024m \
|
||||
-XX:+UseG1GC \
|
||||
-XX:MaxGCPauseMillis=200 \
|
||||
-XX:+HeapDumpOnOutOfMemoryError \
|
||||
-XX:HeapDumpPath="$APP_DIR/logs/heapdump.hprof" \
|
||||
"$JAR_FILE" \
|
||||
--spring.profiles.active=prod \
|
||||
> "$LOG_FILE" 2>&1 &
|
||||
|
||||
NEW_PID=$!
|
||||
echo $NEW_PID > "$PID_FILE"
|
||||
echo "应用已启动 (PID: $NEW_PID)"
|
||||
echo "日志文件:$LOG_FILE"
|
||||
|
||||
# 等待启动
|
||||
echo "等待应用启动..."
|
||||
for i in {1..60}; do
|
||||
if curl -s http://localhost:8480/actuator/health > /dev/null 2>&1; then
|
||||
echo "应用启动成功!"
|
||||
exit 0
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
|
||||
echo "应用启动超时,请检查日志"
|
||||
tail -100 "$LOG_FILE"
|
||||
exit 1
|
||||
EOF
|
||||
|
||||
scp -o StrictHostKeyChecking=no -P "$REMOTE_PORT" \
|
||||
/tmp/deploy-start.sh \
|
||||
"$REMOTE_USER@$REMOTE_HOST:/www/wwwroot/reading-platform/start.sh"
|
||||
|
||||
# 上传停止脚本
|
||||
cat > /tmp/deploy-stop.sh << 'EOF'
|
||||
#!/bin/bash
|
||||
PID_FILE="/www/wwwroot/reading-platform/app.pid"
|
||||
if [ -f "$PID_FILE" ]; then
|
||||
PID=$(cat "$PID_FILE")
|
||||
if kill -0 "$PID" 2>/dev/null; then
|
||||
echo "停止应用 (PID: $PID)..."
|
||||
kill "$PID"
|
||||
sleep 3
|
||||
fi
|
||||
rm -f "$PID_FILE"
|
||||
fi
|
||||
# 确保进程已停止
|
||||
pkill -f "reading-platform-1.0.0.jar" 2>/dev/null || true
|
||||
echo "应用已停止"
|
||||
EOF
|
||||
|
||||
scp -o StrictHostKeyChecking=no -P "$REMOTE_PORT" \
|
||||
/tmp/deploy-stop.sh \
|
||||
"$REMOTE_USER@$REMOTE_HOST:/www/wwwroot/reading-platform/stop.sh"
|
||||
|
||||
# 设置执行权限
|
||||
ssh -o StrictHostKeyChecking=no -p "$REMOTE_PORT" "$REMOTE_USER@$REMOTE_HOST" \
|
||||
"chmod +x /www/wwwroot/reading-platform/start.sh /www/wwwroot/reading-platform/stop.sh"
|
||||
|
||||
log_info "文件上传完成"
|
||||
}
|
||||
|
||||
# 上传前端文件
|
||||
upload_frontend() {
|
||||
log_step "上传前端文件..."
|
||||
|
||||
# 确保前端目录存在
|
||||
ssh -o StrictHostKeyChecking=no -p "$REMOTE_PORT" "$REMOTE_USER@$REMOTE_HOST" \
|
||||
"mkdir -p $REMOTE_FRONTEND_DIR"
|
||||
|
||||
# 上传 dist 目录
|
||||
log_info "上传前端构建文件..."
|
||||
scp -o StrictHostKeyChecking=no -r -P "$REMOTE_PORT" \
|
||||
"reading-platform-frontend/dist/" \
|
||||
"$REMOTE_USER@$REMOTE_HOST:$REMOTE_FRONTEND_DIR/"
|
||||
|
||||
log_info "前端文件上传完成"
|
||||
}
|
||||
|
||||
# 创建配置文件
|
||||
create_config() {
|
||||
log_step "创建生产环境配置..."
|
||||
|
||||
# 创建环境变量文件
|
||||
cat > /tmp/remote-env << EOF
|
||||
# 数据库配置
|
||||
DB_HOST=$DB_HOST
|
||||
DB_PASSWORD=$DB_PASSWORD
|
||||
|
||||
# JWT 配置
|
||||
JWT_SECRET=$JWT_SECRET
|
||||
JWT_EXPIRATION=$JWT_EXPIRATION
|
||||
|
||||
# Redis 配置
|
||||
REDIS_HOST=$REDIS_HOST
|
||||
REDIS_PORT=$REDIS_PORT
|
||||
REDIS_PASSWORD=$REDIS_PASSWORD
|
||||
|
||||
# OSS 配置
|
||||
OSS_ACCESS_KEY_ID=$OSS_ACCESS_KEY_ID
|
||||
OSS_ACCESS_KEY_SECRET=$OSS_ACCESS_KEY_SECRET
|
||||
OSS_BUCKET_NAME=$OSS_BUCKET_NAME
|
||||
OSS_ENDPOINT=$OSS_ENDPOINT
|
||||
EOF
|
||||
|
||||
scp -o StrictHostKeyChecking=no -P "$REMOTE_PORT" \
|
||||
/tmp/remote-env \
|
||||
"$REMOTE_USER@$REMOTE_HOST:/www/wwwroot/reading-platform/.env"
|
||||
|
||||
log_info "配置文件创建完成"
|
||||
}
|
||||
|
||||
# 远程部署
|
||||
remote_deploy() {
|
||||
log_step "执行远程部署..."
|
||||
|
||||
ssh -o StrictHostKeyChecking=no -p "$REMOTE_PORT" "$REMOTE_USER@$REMOTE_HOST" << 'ENDSSH'
|
||||
cd /www/wwwroot/reading-platform
|
||||
|
||||
# 停止旧服务
|
||||
echo "停止旧服务..."
|
||||
bash stop.sh
|
||||
|
||||
# 启动新服务
|
||||
echo "启动新服务..."
|
||||
bash start.sh
|
||||
ENDSSH
|
||||
|
||||
log_info "远程部署完成"
|
||||
}
|
||||
|
||||
# 显示部署信息
|
||||
show_deploy_info() {
|
||||
echo ""
|
||||
echo "=============================================="
|
||||
echo " 部署完成!"
|
||||
echo "=============================================="
|
||||
echo ""
|
||||
echo "后端 API 地址:http://${REMOTE_HOST}:8480"
|
||||
echo "前端访问地址:http://${REMOTE_HOST}"
|
||||
echo "API 文档地址:http://${REMOTE_HOST}:8480/swagger-ui.html"
|
||||
echo ""
|
||||
echo "远程目录:"
|
||||
echo " 后端:/www/wwwroot/reading-platform"
|
||||
echo " 前端:$REMOTE_FRONTEND_DIR"
|
||||
echo ""
|
||||
echo "管理命令:"
|
||||
echo " ssh $REMOTE_USER@$REMOTE_HOST"
|
||||
echo " cd /www/wwwroot/reading-platform"
|
||||
echo " ./start.sh # 启动"
|
||||
echo " ./stop.sh # 停止"
|
||||
echo " ./restart.sh # 重启"
|
||||
echo ""
|
||||
echo "日志查看:"
|
||||
echo " tail -f /www/wwwroot/reading-platform/logs/application.log"
|
||||
echo ""
|
||||
echo "=============================================="
|
||||
}
|
||||
|
||||
# 主函数
|
||||
main() {
|
||||
echo ""
|
||||
echo "=============================================="
|
||||
echo " 幼儿阅读教学服务平台"
|
||||
echo " 一键部署到宝塔面板"
|
||||
echo "=============================================="
|
||||
echo ""
|
||||
|
||||
check_config
|
||||
build_backend
|
||||
build_frontend
|
||||
upload_files
|
||||
upload_frontend
|
||||
create_config
|
||||
remote_deploy
|
||||
show_deploy_info
|
||||
}
|
||||
|
||||
# 执行
|
||||
main "$@"
|
||||
161
deploy.sh
Normal file
161
deploy.sh
Normal file
@ -0,0 +1,161 @@
|
||||
#!/bin/bash
|
||||
|
||||
#===============================================================================
|
||||
# 幼儿阅读教学服务平台 - 一键部署到宝塔面板
|
||||
#
|
||||
# 使用方法:
|
||||
# ./deploy.sh your-server-ip
|
||||
# 或
|
||||
# ./deploy.sh root@your-server-ip
|
||||
#===============================================================================
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
# 颜色
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
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"; }
|
||||
|
||||
# 检查参数
|
||||
if [ -z "$1" ]; then
|
||||
echo ""
|
||||
echo "=============================================="
|
||||
echo " 幼儿阅读教学服务平台"
|
||||
echo " 一键部署到宝塔面板"
|
||||
echo "=============================================="
|
||||
echo ""
|
||||
echo "使用方法:"
|
||||
echo " $0 your-server-ip"
|
||||
echo " $0 root@your-server-ip"
|
||||
echo ""
|
||||
echo "示例:"
|
||||
echo " $0 8.148.151.56"
|
||||
echo " $0 root@8.148.151.56"
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 解析参数
|
||||
REMOTE_HOST="$1"
|
||||
REMOTE_USER="root"
|
||||
if [[ "$1" == *"@"* ]]; then
|
||||
REMOTE_USER=$(echo "$1" | cut -d'@' -f1)
|
||||
REMOTE_HOST=$(echo "$1" | cut -d'@' -f2)
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=============================================="
|
||||
echo " 一键部署到宝塔面板"
|
||||
echo "=============================================="
|
||||
echo ""
|
||||
echo " 服务器:$REMOTE_USER@$REMOTE_HOST"
|
||||
echo ""
|
||||
|
||||
# 检查 SSH 连接
|
||||
log_step "检查 SSH 连接..."
|
||||
if ! ssh -o StrictHostKeyChecking=no "$REMOTE_USER@$REMOTE_HOST" "echo '连接成功'" 2>/dev/null; then
|
||||
log_error "SSH 连接失败,请检查:"
|
||||
echo " 1. 服务器 IP 是否正确"
|
||||
echo " 2. SSH 是否启用(默认端口 22)"
|
||||
echo " 3. 密码/密钥是否正确"
|
||||
echo ""
|
||||
echo " 如果是密码登录,请先执行:"
|
||||
echo " ssh-copy-id $REMOTE_USER@$REMOTE_HOST"
|
||||
exit 1
|
||||
fi
|
||||
log_info "SSH 连接成功"
|
||||
|
||||
# 检查远程服务器
|
||||
log_step "检查远程服务器..."
|
||||
ssh "$REMOTE_USER@$REMOTE_HOST" << 'ENDSSH'
|
||||
# 检查是否安装了宝塔
|
||||
if [ -d "/www/server/panel" ]; then
|
||||
echo "宝塔面板:已安装"
|
||||
else
|
||||
echo "警告:未检测到宝塔面板"
|
||||
fi
|
||||
|
||||
# 检查 JDK
|
||||
if command -v java &> /dev/null; then
|
||||
java_version=$(java -version 2>&1 | head -n 1)
|
||||
echo "Java: $java_version"
|
||||
else
|
||||
echo "警告:未安装 Java"
|
||||
fi
|
||||
|
||||
# 检查 MySQL
|
||||
if command -v mysql &> /dev/null; then
|
||||
echo "MySQL: 已安装"
|
||||
else
|
||||
echo "警告:未安装 MySQL"
|
||||
fi
|
||||
|
||||
# 检查 Nginx
|
||||
if command -v nginx &> /dev/null; then
|
||||
echo "Nginx: 已安装"
|
||||
fi
|
||||
|
||||
# 检查磁盘空间
|
||||
disk_used=$(df -h / | tail -1 | awk '{print $5}')
|
||||
echo "磁盘使用:$disk_used"
|
||||
ENDSSH
|
||||
|
||||
echo ""
|
||||
echo "=============================================="
|
||||
echo " 部署前检查完成"
|
||||
echo "=============================================="
|
||||
echo ""
|
||||
echo " 请确认:"
|
||||
echo " 1. 宝塔面板已安装并可以访问"
|
||||
echo " 2. 已在宝塔中安装 MySQL、Redis、Nginx"
|
||||
echo " 3. 已创建数据库和用户(见 DEPLOY_BAOTA.md)"
|
||||
echo " 4. JDK 17 已安装(或通过宝塔安装)"
|
||||
echo ""
|
||||
read -p "是否继续部署?(y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 部署后端
|
||||
log_step "部署后端..."
|
||||
export REMOTE_USER
|
||||
export REMOTE_HOST
|
||||
bash "$SCRIPT_DIR/deploy-backend.sh"
|
||||
|
||||
# 部署前端
|
||||
log_step "部署前端..."
|
||||
bash "$SCRIPT_DIR/deploy-frontend.sh"
|
||||
|
||||
echo ""
|
||||
echo "=============================================="
|
||||
echo " 部署完成!"
|
||||
echo "=============================================="
|
||||
echo ""
|
||||
echo " 下一步操作:"
|
||||
echo ""
|
||||
echo " 1. 在宝塔面板配置 Nginx 反向代理"
|
||||
echo " 网站 → 设置 → 配置文件"
|
||||
echo " 参考 nginx-baota.conf 中的配置"
|
||||
echo ""
|
||||
echo " 2. 验证后端服务"
|
||||
echo " ssh $REMOTE_USER@$REMOTE_HOST"
|
||||
echo " curl http://localhost:8480/actuator/health"
|
||||
echo ""
|
||||
echo " 3. 访问前端页面"
|
||||
echo " http://$REMOTE_HOST"
|
||||
echo ""
|
||||
echo " 4. 查看日志"
|
||||
echo " 后端:tail -f /www/wwwroot/reading-platform/logs/app.log"
|
||||
echo " Nginx: tail -f /www/wwwlogs/你的域名.error.log"
|
||||
echo ""
|
||||
echo "=============================================="
|
||||
123
nginx-baota.conf
Normal file
123
nginx-baota.conf
Normal file
@ -0,0 +1,123 @@
|
||||
# Nginx 配置 - 幼儿阅读教学服务平台
|
||||
# 在宝塔面板中配置此反向代理
|
||||
|
||||
#==============================
|
||||
# 在宝塔面板的操作步骤:
|
||||
# 1. 网站 → 添加站点 → 创建站点
|
||||
# 2. 域名:输入你的域名(如 reading.ycapp.cn)
|
||||
# 3. 根目录:/www/wwwroot/reading.ycapp.cn
|
||||
# 4. 数据库:PHP 纯静态(前端已构建好)
|
||||
# 5. 确定后,点击网站 → 设置 → 配置文件
|
||||
# 6. 将以下配置粘贴到配置文件中
|
||||
#==============================
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name reading.ycapp.cn; # 修改为你的域名
|
||||
|
||||
# 前端静态文件根目录
|
||||
root /www/wwwroot/reading.ycapp.cn;
|
||||
index index.html;
|
||||
|
||||
# 前端页面路由(Vue Router history 模式支持)
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# 后端 API 反向代理
|
||||
location /api {
|
||||
proxy_pass http://localhost:8480;
|
||||
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 60s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_read_timeout 60s;
|
||||
|
||||
# 跨域支持(如果需要)
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
|
||||
add_header Access-Control-Allow-Headers 'Content-Type, Authorization';
|
||||
|
||||
if ($request_method = OPTIONS) {
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
|
||||
add_header Access-Control-Allow-Headers 'Content-Type, Authorization';
|
||||
add_header Content-Type 'text/plain; charset=utf-8';
|
||||
add_header Content-Length 0;
|
||||
return 204;
|
||||
}
|
||||
}
|
||||
|
||||
# 文件上传代理
|
||||
location /uploads {
|
||||
proxy_pass http://localhost:8480;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
}
|
||||
|
||||
# 静态资源缓存
|
||||
location ~* \.(jpg|jpeg|png|gif|svg|ico|css|js|woff|woff2|ttf|eot)$ {
|
||||
expires 30d;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
|
||||
# 禁止访问隐藏文件
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
}
|
||||
|
||||
# 安全头
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
}
|
||||
|
||||
#==============================
|
||||
# HTTPS 配置(启用 SSL 后使用此配置)
|
||||
#==============================
|
||||
# 在宝塔面板 → 网站 → SSL → Let's Encrypt 免费申请证书
|
||||
# 申请成功后会自动生成以下配置
|
||||
|
||||
# server {
|
||||
# listen 443 ssl http2;
|
||||
# server_name reading.ycapp.cn;
|
||||
# ssl_certificate /www/server/panel/vhost/certs/reading.ycapp.cn/fullchain.pem;
|
||||
# ssl_certificate_key /www/server/panel/vhost/certs/reading.ycapp.cn/privkey.pem;
|
||||
#
|
||||
# # SSL 优化
|
||||
# ssl_protocols TLSv1.2 TLSv1.3;
|
||||
# ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
# ssl_prefer_server_ciphers on;
|
||||
# ssl_session_cache shared:SSL:10m;
|
||||
# ssl_session_timeout 10m;
|
||||
#
|
||||
# root /www/wwwroot/reading.ycapp.cn;
|
||||
# index index.html;
|
||||
#
|
||||
# location / {
|
||||
# try_files $uri $uri/ /index.html;
|
||||
# }
|
||||
#
|
||||
# location /api {
|
||||
# proxy_pass http://localhost:8480;
|
||||
# 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 /uploads {
|
||||
# proxy_pass http://localhost:8480;
|
||||
# }
|
||||
# }
|
||||
#
|
||||
# # HTTP 自动跳转 HTTPS
|
||||
# server {
|
||||
# listen 80;
|
||||
# server_name reading.ycapp.cn;
|
||||
# return 301 https://$server_name$request_uri;
|
||||
# }
|
||||
@ -11,6 +11,29 @@ spring:
|
||||
username: ${DB_USERNAME:reading_platform}
|
||||
password: ${DB_PASSWORD:reading_platform_pwd}
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
druid:
|
||||
initial-size: 5
|
||||
min-idle: 5
|
||||
max-active: 20
|
||||
max-wait: 60000
|
||||
time-between-eviction-runs-millis: 60000
|
||||
min-evictable-idle-time-millis: 300000
|
||||
validation-query: SELECT 1
|
||||
test-while-idle: true
|
||||
test-on-borrow: false
|
||||
test-on-return: false
|
||||
pool-prepared-statements: true
|
||||
max-pool-prepared-statement-per-connection-size: 20
|
||||
stat-view-servlet:
|
||||
enabled: true
|
||||
url-pattern: /druid/*
|
||||
reset-enable: false
|
||||
login-username: admin
|
||||
login-password: admin
|
||||
web-stat-filter:
|
||||
enabled: true
|
||||
url-pattern: /*
|
||||
exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
|
||||
data:
|
||||
redis:
|
||||
# host: ${REDIS_HOST:8.148.151.56}
|
||||
@ -36,32 +59,7 @@ spring:
|
||||
clean-on-validation-error: true
|
||||
out-of-order: true
|
||||
|
||||
# Druid 连接池配置(开发环境)
|
||||
druid:
|
||||
initial-size: 5
|
||||
min-idle: 5
|
||||
max-active: 20
|
||||
max-wait: 60000ms
|
||||
time-between-eviction-runs-millis: 60000ms
|
||||
min-evictable-idle-time-millis: 300000ms
|
||||
validation-query: SELECT 1
|
||||
test-while-idle: true
|
||||
test-on-borrow: false
|
||||
test-on-return: false
|
||||
pool-prepared-statements: true
|
||||
max-pool-prepared-statement-per-connection-size: 20
|
||||
stat-view-servlet:
|
||||
enabled: true
|
||||
url-pattern: /druid/*
|
||||
reset-enable: false
|
||||
login-username: admin
|
||||
login-password: admin
|
||||
web-stat-filter:
|
||||
enabled: true
|
||||
url-pattern: /*
|
||||
exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
|
||||
|
||||
# MyBatis-Plus 配置(开发环境 - 开启 SQL 日志)
|
||||
# MyBatis-Plus 配置
|
||||
mybatis-plus:
|
||||
configuration:
|
||||
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
|
||||
@ -6,39 +6,17 @@ spring:
|
||||
|
||||
datasource:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://${DB_HOST:localhost}:${DB_PORT:3306}/reading_platform?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=true&allowPublicKeyRetrieval=true
|
||||
username: ${DB_USERNAME}
|
||||
password: ${DB_PASSWORD}
|
||||
url: jdbc:mysql://${DB_HOST:47.106.92.245}:${DB_PORT:3306}/lesingle-edu-reading-platform?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=true&allowPublicKeyRetrieval=true
|
||||
username: ${DB_USERNAME:reading_platform}
|
||||
password: ${DB_PASSWORD:WawfXxrMRENydksk}
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
|
||||
data:
|
||||
redis:
|
||||
host: ${REDIS_HOST:localhost}
|
||||
port: ${REDIS_PORT:6379}
|
||||
password: ${REDIS_PASSWORD}
|
||||
database: 0
|
||||
timeout: 10000ms
|
||||
lettuce:
|
||||
pool:
|
||||
max-active: 16
|
||||
max-wait: -1ms
|
||||
max-idle: 8
|
||||
min-idle: 2
|
||||
|
||||
flyway:
|
||||
enabled: true
|
||||
locations: classpath:db/migration
|
||||
clean-disabled: true
|
||||
validate-on-migrate: true
|
||||
|
||||
# Druid 连接池配置(生产环境)
|
||||
druid:
|
||||
initial-size: 10
|
||||
min-idle: 10
|
||||
max-active: 50
|
||||
max-wait: 30000ms
|
||||
time-between-eviction-runs-millis: 60000ms
|
||||
min-evictable-idle-time-millis: 300000ms
|
||||
max-wait: 30000
|
||||
time-between-eviction-runs-millis: 60000
|
||||
min-evictable-idle-time-millis: 300000
|
||||
validation-query: SELECT 1
|
||||
test-while-idle: true
|
||||
test-on-borrow: false
|
||||
@ -56,7 +34,28 @@ druid:
|
||||
url-pattern: /*
|
||||
exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
|
||||
|
||||
# MyBatis-Plus 配置(生产环境 - 关闭 SQL 日志)
|
||||
data:
|
||||
redis:
|
||||
host: ${REDIS_HOST:127.0.0.1}
|
||||
port: ${REDIS_PORT:6379}
|
||||
password: ${REDIS_PASSWORD:laomo_redis123}
|
||||
database: 7
|
||||
timeout: 10000ms
|
||||
lettuce:
|
||||
pool:
|
||||
max-active: 16
|
||||
max-wait: -1ms
|
||||
max-idle: 8
|
||||
min-idle: 2
|
||||
|
||||
flyway:
|
||||
enabled: true
|
||||
locations: classpath:db/migration
|
||||
clean-disabled: true
|
||||
validate-on-migrate: true
|
||||
skip-patterns: V7_,V8_,V10_,V43_
|
||||
|
||||
# MyBatis-Plus 配置
|
||||
mybatis-plus:
|
||||
configuration:
|
||||
map-underscore-to-camel-case: true
|
||||
|
||||
@ -10,6 +10,29 @@ spring:
|
||||
username: ${DB_USERNAME:reading_platform}
|
||||
password: ${DB_PASSWORD:reading_platform_pwd}
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
druid:
|
||||
initial-size: 5
|
||||
min-idle: 5
|
||||
max-active: 20
|
||||
max-wait: 60000
|
||||
time-between-eviction-runs-millis: 60000
|
||||
min-evictable-idle-time-millis: 300000
|
||||
validation-query: SELECT 1
|
||||
test-while-idle: true
|
||||
test-on-borrow: false
|
||||
test-on-return: false
|
||||
pool-prepared-statements: true
|
||||
max-pool-prepared-statement-per-connection-size: 20
|
||||
stat-view-servlet:
|
||||
enabled: true
|
||||
url-pattern: /druid/*
|
||||
reset-enable: false
|
||||
login-username: admin
|
||||
login-password: admin
|
||||
web-stat-filter:
|
||||
enabled: true
|
||||
url-pattern: /*
|
||||
exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
|
||||
|
||||
data:
|
||||
redis:
|
||||
@ -31,32 +54,7 @@ spring:
|
||||
clean-disabled: true
|
||||
validate-on-migrate: true
|
||||
|
||||
# Druid 连接池配置(测试环境)
|
||||
druid:
|
||||
initial-size: 5
|
||||
min-idle: 5
|
||||
max-active: 20
|
||||
max-wait: 60000ms
|
||||
time-between-eviction-runs-millis: 60000ms
|
||||
min-evictable-idle-time-millis: 300000ms
|
||||
validation-query: SELECT 1
|
||||
test-while-idle: true
|
||||
test-on-borrow: false
|
||||
test-on-return: false
|
||||
pool-prepared-statements: true
|
||||
max-pool-prepared-statement-per-connection-size: 20
|
||||
stat-view-servlet:
|
||||
enabled: true
|
||||
url-pattern: /druid/*
|
||||
reset-enable: false
|
||||
login-username: admin
|
||||
login-password: admin
|
||||
web-stat-filter:
|
||||
enabled: true
|
||||
url-pattern: /*
|
||||
exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
|
||||
|
||||
# MyBatis-Plus 配置(测试环境)
|
||||
# MyBatis-Plus 配置
|
||||
mybatis-plus:
|
||||
configuration:
|
||||
map-underscore-to-camel-case: true
|
||||
|
||||
@ -1,12 +0,0 @@
|
||||
-- =====================================================
|
||||
-- 清理 V10 失败的 Flyway 迁移记录
|
||||
-- 使用方法:在 MySQL 客户端中执行此脚本
|
||||
-- =====================================================
|
||||
|
||||
-- 删除 V10 失败记录
|
||||
DELETE FROM flyway_schema_history WHERE version = '10';
|
||||
|
||||
-- 验证清理结果
|
||||
SELECT * FROM flyway_schema_history ORDER BY installed_rank DESC LIMIT 5;
|
||||
|
||||
-- 确认后,重启应用,Flyway 将重新执行 V10 迁移
|
||||
@ -0,0 +1,141 @@
|
||||
# Flyway 迁移脚本部署说明
|
||||
|
||||
## 正式环境部署指南
|
||||
|
||||
### 1. Flyway 配置确认
|
||||
|
||||
生产环境配置 `application-prod.yml` 已正确设置:
|
||||
|
||||
```yaml
|
||||
spring:
|
||||
flyway:
|
||||
enabled: true # ✅ 必须设置为 true
|
||||
locations: classpath:db/migration
|
||||
clean-disabled: true # ✅ 禁止清理数据库
|
||||
validate-on-migrate: true # ✅ 迁移前验证
|
||||
skip-patterns: V7_,V8_,V10_,V43_ # ✅ 跳过测试数据脚本
|
||||
```
|
||||
|
||||
### 2. 测试数据脚本处理
|
||||
|
||||
生产环境通过 `skip-patterns` 配置跳过以下测试数据脚本:
|
||||
|
||||
| 脚本文件 | 内容 | 状态 |
|
||||
|---------|------|------|
|
||||
| `V7__add_test_data.sql` | 测试课程、套餐、教师、家长、学生数据 | ⚠️ 生产环境跳过 |
|
||||
| `V8__add_tenant_package_test_data.sql` | 测试租户套餐数据 | ⚠️ 生产环境跳过 |
|
||||
| `V10__add_relation_test_data.sql` | 测试关联数据(课程资源、活动、任务等) | ⚠️ 生产环境跳过 |
|
||||
| `V43__add_student_class_history_data.sql` | 测试学生班级关联数据 | ⚠️ 生产环境跳过 |
|
||||
|
||||
**注意**:
|
||||
- 开发和测试环境**不受影响**,会继续执行所有脚本
|
||||
- 生产环境通过 `skip-patterns` 配置自动跳过带 `V7_`、`V8_`、`V10_`、`V43_` 前缀的脚本
|
||||
|
||||
### 3. 正式环境迁移执行顺序
|
||||
|
||||
Flyway 将按以下顺序执行迁移脚本(生产环境跳过 V7, V8, V10, V43):
|
||||
|
||||
```
|
||||
V1 → V2 → V3 → V4 → V5 → V6 → V9 → V11 → V12 → V13 → V14 → V15 → V16
|
||||
→ V26 → V27 → V28 → V29 → V31 → V32 → V33 → V34 → V35 → V36 → V37
|
||||
→ V38 → V39 → V40 → V41 → V42 → V44 → V45 → V46 → V47 → V48 → V49 → V50
|
||||
```
|
||||
|
||||
**跳过的脚本**:V7, V8, V10, V43(测试数据)
|
||||
|
||||
### 4. 部署步骤
|
||||
|
||||
#### 步骤 1:准备数据库
|
||||
|
||||
```sql
|
||||
-- 创建数据库(如未创建)
|
||||
CREATE DATABASE IF NOT EXISTS `lesingle-edu-reading-platform`
|
||||
DEFAULT CHARACTER SET utf8mb4
|
||||
COLLATE utf8mb4_unicode_ci;
|
||||
|
||||
-- 创建数据库用户(推荐使用专用用户)
|
||||
CREATE USER 'reading_platform'@'%' IDENTIFIED BY '强密码';
|
||||
GRANT ALL PRIVILEGES ON `lesingle-edu-reading-platform`.* TO 'reading_platform'@'%';
|
||||
FLUSH PRIVILEGES;
|
||||
```
|
||||
|
||||
#### 步骤 2:配置环境变量
|
||||
|
||||
```bash
|
||||
# 数据库配置
|
||||
export DB_HOST=你的数据库主机
|
||||
export DB_PORT=3306
|
||||
export DB_USERNAME=reading_platform
|
||||
export DB_PASSWORD=强密码
|
||||
|
||||
# Redis 配置
|
||||
export REDIS_HOST=你的 Redis 主机
|
||||
export REDIS_PORT=6379
|
||||
|
||||
# JWT 密钥(必须设置)
|
||||
export JWT_SECRET=你的 JWT 密钥(建议 32 位以上随机字符串)
|
||||
|
||||
# OSS 配置(可选,使用默认值或设置)
|
||||
export OSS_ENDPOINT=oss-cn-shenzhen.aliyuncs.com
|
||||
export OSS_ACCESS_KEY_ID=你的 AccessKey
|
||||
export OSS_ACCESS_KEY_SECRET=你的 AccessKey 密钥
|
||||
export OSS_BUCKET_NAME=lesingle-kid-course
|
||||
```
|
||||
|
||||
#### 步骤 3:启动应用
|
||||
|
||||
```bash
|
||||
# 使用生产环境配置启动
|
||||
java -jar reading-platform.jar --spring.profiles.active=prod
|
||||
```
|
||||
|
||||
#### 步骤 4:验证迁移
|
||||
|
||||
启动后检查日志,确认 Flyway 迁移成功:
|
||||
|
||||
```
|
||||
Flyway migration completed successfully
|
||||
Applied X migrations to database
|
||||
```
|
||||
|
||||
检查数据库中的迁移历史表:
|
||||
|
||||
```sql
|
||||
USE `lesingle-edu-reading-platform`;
|
||||
SELECT * FROM flyway_schema_history ORDER BY installed_rank;
|
||||
```
|
||||
|
||||
### 5. 初始化超管账号
|
||||
|
||||
迁移完成后,数据库中没有超管账号,需要通过超管端创建第一个超管账号。
|
||||
|
||||
### 6. 注意事项
|
||||
|
||||
1. **测试数据脚本跳过** - 生产环境通过 `skip-patterns` 配置跳过 V7, V8, V10, V43
|
||||
2. **开发和测试环境不受影响** - 其他环境继续执行所有脚本(包括测试数据)
|
||||
3. **JWT 密钥必须设置** - 生产环境必须通过环境变量设置 JWT_SECRET
|
||||
4. **数据库权限最小化** - 建议使用专用数据库用户,仅授予必要权限
|
||||
5. **备份数据库** - 部署前建议备份数据库
|
||||
6. **Flyway 历史记录** - `flyway_schema_history` 表记录了所有迁移历史,不要手动修改
|
||||
|
||||
### 7. 迁移脚本清单
|
||||
|
||||
| 版本号 | 脚本文件 | 描述 |
|
||||
| --- | --- | --- |
|
||||
| V1 | `V1__init_schema.sql` | 初始化基础表结构 |
|
||||
| V2 | `V2__add_course_tables.sql` | 添加课程相关表 |
|
||||
| V3 | `V3__add_business_tables.sql` | 添加业务表 |
|
||||
| V4 | `V4__add_resource_tables.sql` | 添加资源表 |
|
||||
| V5 | `V5__fix_password.sql` | 修复密码字段 |
|
||||
| V6 | `V6__fix_status.sql` | 修复状态字段 |
|
||||
| V9 | `V9__fix_resource_and_tenant_tables.sql` | 修复资源和租户表 |
|
||||
| V11-V16 | `V11-V16__*.sql` | 自增 ID、字段修复 |
|
||||
| V26-V29 | `V26-V29__*.sql` | 添加集体课型、排课引用数据等 |
|
||||
| V31-V35 | `V31-V35__*.sql` | 删除废弃字段、套餐结构重构 |
|
||||
| V36-V42 | `V36-V42__*.sql` | 重命名表、清理旧表、优化关联表 |
|
||||
| V44-V50 | `V44-V50__*.sql` | 添加阅读任务功能、主题色、操作日志扩展 |
|
||||
|
||||
---
|
||||
|
||||
**最后更新**: 2026-03-25
|
||||
**适用版本**: 生产环境部署
|
||||
@ -15,10 +15,6 @@ SET FOREIGN_KEY_CHECKS = 0;
|
||||
SELECT
|
||||
'=== 检查 course_package 表中需要迁移的数据 ===' as info;
|
||||
|
||||
-- 如果有需要保留的数据,可以先备份
|
||||
CREATE TABLE IF NOT EXISTS course_package_backup AS
|
||||
SELECT * FROM course_package WHERE 1=0;
|
||||
|
||||
-- =====================================================
|
||||
-- 第二步:删除旧的关联表
|
||||
-- =====================================================
|
||||
|
||||
Loading…
Reference in New Issue
Block a user