run_dataops.sh 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. #!/usr/bin/env bash
  2. set -euo pipefail
  3. APP_DIR="${APP_DIR:-/opt/dataops-platform}"
  4. ENV_FILE="${APP_ENV_FILE:-/etc/dataops-platform/dataops.env}"
  5. LOG_DIR="${APP_DIR}/logs"
  6. VENV_DIR="${APP_DIR}/venv"
  7. mkdir -p "${LOG_DIR}"
  8. if [[ -f "${ENV_FILE}" ]]; then
  9. if [[ ! -r "${ENV_FILE}" ]]; then
  10. echo "无法读取环境变量文件: ${ENV_FILE} (用户: $(id -un))" >&2
  11. echo "请执行: sudo chown root:ubuntu ${ENV_FILE} && sudo chmod 640 ${ENV_FILE}" >&2
  12. exit 1
  13. fi
  14. set -a
  15. # shellcheck disable=SC1090
  16. source <(sed 's/\r$//' "${ENV_FILE}" | sed '1s/^\xEF\xBB\xBF//')
  17. set +a
  18. fi
  19. if [[ -z "${DEEPSEEK_API_KEY:-}" && -z "${LLM_API_KEY:-}" ]]; then
  20. echo "[run_dataops] WARN: DEEPSEEK_API_KEY 未从 ${ENV_FILE} 加载" >&2
  21. fi
  22. export FLASK_ENV="${FLASK_ENV:-production}"
  23. export APP_ENV_FILE="${ENV_FILE}"
  24. export APP_DIR="${APP_DIR:-/opt/dataops-platform}"
  25. export PYTHONPATH="${APP_DIR}${PYTHONPATH:+:${PYTHONPATH}}"
  26. LISTEN_HOST="${LISTEN_HOST:-0.0.0.0}"
  27. LISTEN_PORT="${LISTEN_PORT:-5500}"
  28. GUNICORN_WORKERS="${GUNICORN_WORKERS:-4}"
  29. GUNICORN_TIMEOUT="${GUNICORN_TIMEOUT:-120}"
  30. # 与 Flask ProductionConfig.PORT 保持一致
  31. export PORT="${PORT:-${LISTEN_PORT}}"
  32. # 统一写入绝对路径,避免相对路径落到 APP_DIR 根目录
  33. export LOG_DIR="${LOG_DIR:-${APP_DIR}/logs}"
  34. mkdir -p "${LOG_DIR}"
  35. if [[ -z "${LOG_FILE:-}" || "${LOG_FILE}" != /* ]]; then
  36. log_filename="${LOG_FILE:-flask_production.log}"
  37. log_filename="${log_filename##*/}"
  38. export LOG_FILE="${LOG_DIR}/${log_filename}"
  39. fi
  40. cd "${APP_DIR}"
  41. if [[ ! -x "${VENV_DIR}/bin/gunicorn" ]]; then
  42. echo "gunicorn 未安装: ${VENV_DIR}/bin/gunicorn" >&2
  43. exit 1
  44. fi
  45. echo "[run_dataops] binding ${LISTEN_HOST}:${LISTEN_PORT} workers=${GUNICORN_WORKERS} log=${LOG_FILE}" >&2
  46. if [[ ! -f "${APP_DIR}/gunicorn_config.py" ]]; then
  47. echo "缺少 gunicorn 配置: ${APP_DIR}/gunicorn_config.py" >&2
  48. exit 1
  49. fi
  50. # 启动前验证 Flask 应用能正常加载(失败时错误写入 supervisor 日志)
  51. if ! "${VENV_DIR}/bin/python" -c "from app import create_app; create_app(); print('app bootstrap ok')" >&2; then
  52. echo "Flask 应用预检失败,请检查 ${ENV_FILE} 与依赖配置" >&2
  53. exit 1
  54. fi
  55. exec "${VENV_DIR}/bin/gunicorn" \
  56. --config "${APP_DIR}/gunicorn_config.py" \
  57. --bind "${LISTEN_HOST}:${LISTEN_PORT}" \
  58. --workers "${GUNICORN_WORKERS}" \
  59. --timeout "${GUNICORN_TIMEOUT}" \
  60. --access-logfile "${LOG_DIR}/gunicorn_access.log" \
  61. --error-logfile "${LOG_DIR}/gunicorn_error.log" \
  62. --capture-output \
  63. --enable-stdio-inheritance \
  64. --log-level info \
  65. wsgi:application