- 将默认数据库用户名从 your_user 改为 postgresql,明确用户名字段说明 - 修改 .env.example 中 DEBUG 默认为 True,方便本地调试 - 更新 deploy-docker-compose.sh 脚本中 DEBUG 默认值为 True,保持一致性 - 保持数据库连接字符串格式正确,确保环境变量配置一致
218 lines
6.5 KiB
Bash
218 lines
6.5 KiB
Bash
#!/bin/bash
|
||
# Spug 自动部署脚本 - 直接粘贴到 Spug 执行
|
||
# 用途:医院绩效考核系统传统部署(非 Docker)
|
||
# 适用:服务器无法访问 Docker Hub 的情况
|
||
|
||
set -e
|
||
|
||
# ==================== 配置参数 ====================
|
||
PROJECT_DIR="${SPUG_DEPLOY_DIR:-/data/spug/service/hospital_performance}"
|
||
GIT_REPO="${SPUG_GIT_URL:-https://gitea.gentronhealth.com/chenqi/hospital_performance.git}"
|
||
GIT_BRANCH="${SPUG_GIT_BRANCH:-main}"
|
||
|
||
# 服务配置
|
||
BACKEND_PORT="${BACKEND_PORT:-5757}"
|
||
FRONTEND_PORT="${FRONTEND_PORT:-5758}"
|
||
|
||
# 环境变量
|
||
export DATABASE_HOST="${DATABASE_HOST:-192.168.110.252}"
|
||
export DATABASE_PORT="${DATABASE_PORT:-15432}"
|
||
export DATABASE_USER="${DATABASE_USER:-postgresql}"
|
||
export DATABASE_PASSWORD="${DATABASE_PASSWORD:-Jchl1528}"
|
||
export DATABASE_NAME="${DATABASE_NAME:-hospital_performance}"
|
||
export SECRET_KEY="${SECRET_KEY:-change-this-secret-key-in-production}"
|
||
export DEBUG="${DEBUG:-True}"
|
||
|
||
# 构建完整的 DATABASE_URL(后端使用此变量)
|
||
export DATABASE_URL="postgresql+asyncpg://${DATABASE_USER}:${DATABASE_PASSWORD}@${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}"
|
||
|
||
# 日志配置
|
||
LOG_FILE="/tmp/spug-deploy-$(date +%Y%m%d_%H%M%S).log"
|
||
|
||
echo "========================================"
|
||
echo "Spug Docker Compose 自动部署开始"
|
||
echo "项目目录:${PROJECT_DIR}"
|
||
echo "Git 分支:${GIT_BRANCH}"
|
||
echo "========================================"
|
||
|
||
# ================= Step 1: 更新代码 =================
|
||
echo "========== 更新代码 =========="
|
||
|
||
# 确保目录存在
|
||
mkdir -p "${PROJECT_DIR}"
|
||
cd "${PROJECT_DIR}"
|
||
|
||
if [ ! -d ".git" ]; then
|
||
echo "首次部署,克隆仓库..."
|
||
# 检查目录是否为空,非空则备份
|
||
if [ "$(ls -A ${PROJECT_DIR} 2>/dev/null)" ]; then
|
||
echo "目录非空,备份现有文件..."
|
||
backup_dir="${PROJECT_DIR}_backup_$(date +%Y%m%d_%H%M%S)"
|
||
mkdir -p "${backup_dir}"
|
||
mv ${PROJECT_DIR}/* ${PROJECT_DIR}/.[!.]* ${backup_dir}/ 2>/dev/null || true
|
||
echo "已备份到:${backup_dir}"
|
||
fi
|
||
git clone "${GIT_REPO}" .
|
||
git checkout "${GIT_BRANCH}"
|
||
else
|
||
echo "更新现有代码..."
|
||
git fetch origin "${GIT_BRANCH}"
|
||
git reset --hard "origin/${GIT_BRANCH}"
|
||
git clean -fd
|
||
fi
|
||
|
||
commit_hash=$(git rev-parse --short HEAD)
|
||
commit_msg=$(git log -1 --pretty=format:"%s")
|
||
echo "✅ 代码更新完成,当前版本:${commit_hash} - ${commit_msg}"
|
||
|
||
# ================= Step 2: 停止旧服务 =================
|
||
echo "========== 停止旧服务 =========="
|
||
|
||
# 停止旧的后端进程
|
||
OLD_BACKEND_PID=$(ps -ef | grep "uvicorn.*app.main:app" | grep -v grep | awk '{print $2}')
|
||
if [ -n "$OLD_BACKEND_PID" ]; then
|
||
echo "停止旧的后端进程 $OLD_BACKEND_PID"
|
||
kill -9 $OLD_BACKEND_PID || true
|
||
fi
|
||
|
||
echo "✅ 旧服务已停止"
|
||
|
||
# ================= Step 3: 创建环境配置 =================
|
||
echo "========== 创建环境配置 =========="
|
||
cd "${PROJECT_DIR}/backend"
|
||
|
||
# 创建 .env 文件
|
||
cat > .env <<ENVEOF
|
||
# 数据库配置
|
||
DATABASE_URL=${DATABASE_URL}
|
||
|
||
# JWT 配置
|
||
SECRET_KEY=${SECRET_KEY}
|
||
|
||
# 调试模式
|
||
DEBUG=${DEBUG}
|
||
ENVEOF
|
||
|
||
echo "✅ 环境配置已创建"
|
||
|
||
# ================= Step 4: 安装依赖并部署后端 =================
|
||
echo "========== 部署后端 =========="
|
||
cd "${PROJECT_DIR}/backend"
|
||
|
||
# 创建虚拟环境
|
||
if [ ! -d "venv" ]; then
|
||
echo "创建 Python 虚拟环境..."
|
||
python3 -m venv venv
|
||
fi
|
||
|
||
# 激活虚拟环境
|
||
source venv/bin/activate
|
||
|
||
# 安装依赖
|
||
echo "安装 Python 依赖..."
|
||
pip install --upgrade pip -i https://pypi.tuna.tsinghua.edu.cn/simple
|
||
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
|
||
|
||
# 数据库迁移
|
||
echo "执行数据库迁移..."
|
||
alembic upgrade head || true
|
||
|
||
# 启动后端
|
||
echo "启动后端服务..."
|
||
mkdir -p logs
|
||
nohup venv/bin/uvicorn app.main:app --host 0.0.0.0 --port ${BACKEND_PORT} --workers 4 > logs/backend.log 2>&1 &
|
||
echo "✅ 后端服务已启动,端口 ${BACKEND_PORT}"
|
||
|
||
# ================= Step 5: 构建前端 =================
|
||
echo "========== 构建前端 =========="
|
||
cd "${PROJECT_DIR}/frontend"
|
||
|
||
# 检查 node_modules
|
||
if [ ! -d "node_modules" ]; then
|
||
echo "安装前端依赖..."
|
||
npm install --registry=https://registry.npmmirror.com
|
||
else
|
||
echo "更新前端依赖..."
|
||
npm update --registry=https://registry.npmmirror.com
|
||
fi
|
||
|
||
# 构建前端
|
||
echo "构建前端项目..."
|
||
npm run build
|
||
echo "✅ 前端构建完成"
|
||
|
||
# ================= Step 6: 部署前端到 Nginx =================
|
||
echo "========== 部署前端 =========="
|
||
NGINX_HTML="/var/www/hospital_performance_html"
|
||
mkdir -p ${NGINX_HTML}
|
||
rm -rf ${NGINX_HTML}/*
|
||
cp -r ${PROJECT_DIR}/frontend/dist/* ${NGINX_HTML}/
|
||
|
||
# 创建 Nginx 配置
|
||
cat > /etc/nginx/conf.d/hospital_performance.conf <<EOF
|
||
server {
|
||
listen ${FRONTEND_PORT};
|
||
server_name localhost;
|
||
root ${NGINX_HTML};
|
||
index index.html;
|
||
|
||
location /api/ {
|
||
proxy_pass http://127.0.0.1:${BACKEND_PORT};
|
||
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 / {
|
||
try_files \$uri \$uri/ /index.html;
|
||
}
|
||
}
|
||
EOF
|
||
|
||
# 重启 Nginx
|
||
echo "重启 Nginx..."
|
||
systemctl restart nginx || nginx -s reload || true
|
||
echo "✅ 前端部署完成"
|
||
|
||
# ================= Step 7: 等待并健康检查 =================
|
||
echo "========== 执行健康检查 =========="
|
||
echo "等待服务启动..."
|
||
sleep 10
|
||
|
||
max_attempts=10
|
||
attempt=1
|
||
|
||
while [ $attempt -le $max_attempts ]; do
|
||
if curl -f -s "http://localhost:${BACKEND_PORT}/health" > /dev/null 2>&1; then
|
||
echo "✅ 后端 API 健康检查通过"
|
||
break
|
||
else
|
||
if [ $attempt -eq $max_attempts ]; then
|
||
echo "❌ 后端 API 健康检查失败"
|
||
echo "最近日志如下:"
|
||
tail -n 50 ${PROJECT_DIR}/backend/logs/backend.log || echo "日志文件不存在"
|
||
exit 1
|
||
fi
|
||
echo "后端服务未就绪,等待... (${attempt}/${max_attempts})"
|
||
sleep 5
|
||
attempt=$((attempt + 1))
|
||
fi
|
||
done
|
||
|
||
# ================= Step 8: 查看状态 =================
|
||
echo "========== 服务状态 =========="
|
||
echo "后端进程:"
|
||
ps -ef | grep "uvicorn.*app.main:app" | grep -v grep
|
||
echo ""
|
||
echo "Nginx 状态:"
|
||
systemctl status nginx --no-pager || true
|
||
|
||
# ================= Step 9: 完成 =================
|
||
echo "✅ 部署完成"
|
||
|
||
echo "========================================"
|
||
echo "🎉 部署成功完成!"
|
||
echo "后端地址:http://localhost:${BACKEND_PORT}"
|
||
echo "前端地址:http://localhost:${FRONTEND_PORT}"
|
||
echo "========================================"
|