build_release.sh 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. #!/bin/bash
  2. # 遇到错误立即退出
  3. set -e
  4. echo "========================================================"
  5. echo " ShuDao SafeAI 生产环境一键部署脚本 (Python)"
  6. echo "========================================================"
  7. echo ""
  8. # 设置路径变量
  9. # Paths (robust to where you run the script from)
  10. SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
  11. # Backend dir: contains main.py + requirements.txt
  12. if [ -f "$SCRIPT_DIR/main.py" ]; then
  13. BACKEND_DIR="$SCRIPT_DIR"
  14. PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
  15. elif [ -f "$SCRIPT_DIR/shudao-chat-py/main.py" ]; then
  16. PROJECT_ROOT="$SCRIPT_DIR"
  17. BACKEND_DIR="$PROJECT_ROOT/shudao-chat-py"
  18. elif [ -f "$PWD/main.py" ]; then
  19. BACKEND_DIR="$PWD"
  20. PROJECT_ROOT="$(cd "$PWD/.." && pwd)"
  21. else
  22. echo "[ERROR] Cannot locate backend directory (main.py)."
  23. echo " Run this script from shudao-main/ or shudao-chat-py/."
  24. exit 1
  25. fi
  26. # Frontend dir: contains package.json
  27. if [ -d "$PROJECT_ROOT/shudao-vue-frontend" ]; then
  28. FRONTEND_DIR="$PROJECT_ROOT/shudao-vue-frontend"
  29. elif [ -d "$PROJECT_ROOT/shudao-main/shudao-vue-frontend" ]; then
  30. # Backward compatibility for layouts like: /opt/www/{shudao-chat-py, shudao-main/shudao-vue-frontend}
  31. FRONTEND_DIR="$PROJECT_ROOT/shudao-main/shudao-vue-frontend"
  32. else
  33. echo "[ERROR] Cannot locate frontend directory (shudao-vue-frontend)."
  34. exit 1
  35. fi
  36. ROOT_DIR="$BACKEND_DIR"
  37. DEPLOY_DIR="/opt/www/shudao-chat-py"
  38. SERVICE_NAME="shudao-chat-py"
  39. SERVICE_PORT=22001
  40. PYTHON_BIN="python3.11"
  41. VENV_DIR="$DEPLOY_DIR/venv"
  42. # 1. 前端构建
  43. echo "[1/9] 正在构建前端项目 (Vue)..."
  44. cd "$FRONTEND_DIR"
  45. npm run build
  46. if [ $? -ne 0 ]; then
  47. echo "[ERROR] 前端构建失败!请检查错误信息。"
  48. exit 1
  49. fi
  50. echo "[SUCCESS] 前端构建完成。"
  51. echo ""
  52. # 2. 清理后端旧资源
  53. echo "[2/9] 清理后端旧资源..."
  54. cd "$BACKEND_DIR"
  55. rm -rf "$BACKEND_DIR/assets" 2>/dev/null || true
  56. rm -rf "$BACKEND_DIR/views" 2>/dev/null || true
  57. echo "[SUCCESS] 清理完成。"
  58. echo ""
  59. # 3. 复制新资源
  60. echo "[3/9] 整合前端资源到后端..."
  61. mkdir -p "$BACKEND_DIR/assets"
  62. mkdir -p "$BACKEND_DIR/views"
  63. cp -r "$FRONTEND_DIR/dist/assets/"* "$BACKEND_DIR/assets/"
  64. cp "$FRONTEND_DIR/dist/index.html" "$BACKEND_DIR/views/index.html"
  65. echo "[SUCCESS] 资源整合完成。"
  66. echo ""
  67. # 4. 检查并复制生产环境配置
  68. echo "[4/9] 配置生产环境..."
  69. if [ -f "$BACKEND_DIR/config.yaml" ]; then
  70. echo "[INFO] 使用现有 config.yaml"
  71. else
  72. if [ -f "$BACKEND_DIR/config.example.yaml" ]; then
  73. cp "$BACKEND_DIR/config.example.yaml" "$BACKEND_DIR/config.yaml"
  74. echo "[WARNING] 已从 config.example.yaml 创建 config.yaml,请手动配置!"
  75. else
  76. echo "[ERROR] 未找到配置文件模板!"
  77. exit 1
  78. fi
  79. fi
  80. # 检查 .env 文件
  81. if [ ! -f "$BACKEND_DIR/.env" ]; then
  82. echo "[WARNING] 未找到 .env 文件,请确保环境变量已正确配置!"
  83. echo "[INFO] 可以从 .env.example 复制并修改"
  84. fi
  85. echo "[SUCCESS] 配置检查完成。"
  86. echo ""
  87. # 5. 停止旧服务
  88. echo "[5/9] 停止旧服务..."
  89. pkill -f "uvicorn main:app" 2>/dev/null || true
  90. pkill -f "$SERVICE_NAME" 2>/dev/null || true
  91. sleep 2
  92. # 确认服务已停止
  93. if pgrep -f "uvicorn main:app" > /dev/null 2>&1; then
  94. echo "[WARNING] 服务未完全停止,强制终止..."
  95. pkill -9 -f "uvicorn main:app" 2>/dev/null || true
  96. sleep 1
  97. fi
  98. echo "[SUCCESS] 旧服务已停止。"
  99. echo ""
  100. # 6. 部署到目标目录
  101. echo "[6/9] 部署到 $DEPLOY_DIR..."
  102. mkdir -p "$DEPLOY_DIR"
  103. rsync -av --exclude='__pycache__' \
  104. --exclude='*.pyc' \
  105. --exclude='venv' \
  106. --exclude='.git' \
  107. --exclude='logs/*.log' \
  108. --exclude='.env' \
  109. "$BACKEND_DIR/" "$DEPLOY_DIR/"
  110. # 如果 .env 存在,复制过去
  111. if [ -f "$BACKEND_DIR/.env" ]; then
  112. cp "$BACKEND_DIR/.env" "$DEPLOY_DIR/"
  113. fi
  114. echo "[SUCCESS] 部署完成。"
  115. echo ""
  116. # 7. 创建/更新虚拟环境
  117. echo "[7/9] 配置 Python 虚拟环境..."
  118. cd "$DEPLOY_DIR"
  119. if [ ! -d "$VENV_DIR" ]; then
  120. echo "[INFO] 创建新的虚拟环境..."
  121. $PYTHON_BIN -m venv "$VENV_DIR"
  122. fi
  123. # 激活虚拟环境并安装依赖
  124. source "$VENV_DIR/bin/activate"
  125. pip install --upgrade pip -i https://pypi.tuna.tsinghua.edu.cn/simple
  126. pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
  127. if [ $? -ne 0 ]; then
  128. echo "[ERROR] 依赖安装失败!"
  129. exit 1
  130. fi
  131. echo "[SUCCESS] Python 环境配置完成。"
  132. echo ""
  133. # 8. 创建日志目录
  134. echo "[8/9] 准备运行环境..."
  135. mkdir -p "$DEPLOY_DIR/logs"
  136. mkdir -p "$DEPLOY_DIR/static"
  137. chmod +x "$DEPLOY_DIR/main.py" 2>/dev/null || true
  138. echo "[SUCCESS] 运行环境准备完成。"
  139. echo ""
  140. # 9. 启动新服务
  141. echo "[9/9] 启动新服务..."
  142. cd "$DEPLOY_DIR"
  143. # 使用 nohup 启动服务(生产环境建议使用 systemd 或 supervisor)
  144. nohup "$VENV_DIR/bin/python" -m uvicorn main:app \
  145. --host 0.0.0.0 \
  146. --port $SERVICE_PORT \
  147. --workers 4 \
  148. > logs/app.log 2>&1 &
  149. sleep 3
  150. # 检查服务状态
  151. if pgrep -f "uvicorn main:app" > /dev/null 2>&1; then
  152. echo "[SUCCESS] 服务已启动!"
  153. echo ""
  154. echo "========================================================"
  155. echo " 生产环境部署完成!"
  156. echo "========================================================"
  157. echo ""
  158. echo "服务状态: 运行中"
  159. echo "服务端口: $SERVICE_PORT"
  160. echo "部署目录: $DEPLOY_DIR"
  161. echo "日志文件: $DEPLOY_DIR/logs/app.log"
  162. echo "虚拟环境: $VENV_DIR"
  163. echo ""
  164. echo "查看日志: tail -f $DEPLOY_DIR/logs/app.log"
  165. echo "查看进程: ps aux | grep uvicorn"
  166. echo "停止服务: pkill -f 'uvicorn main:app'"
  167. echo ""
  168. echo "[建议] 生产环境请使用 systemd 管理服务"
  169. echo " 参考: $DEPLOY_DIR/deploy/shudao-chat-py.service"
  170. echo ""
  171. else
  172. echo "[ERROR] 服务启动失败!"
  173. echo "请检查日志:"
  174. tail -30 "$DEPLOY_DIR/logs/app.log"
  175. exit 1
  176. fi