| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- #!/usr/bin/env bash
- #
- # DataOps Platform 生产部署脚本
- # - 安装 /etc/dataops-platform/dataops.env
- # - 创建/更新虚拟环境
- # - 配置 Supervisor,通过 run_dataops.sh 加载环境变量并启动 Gunicorn
- #
- set -euo pipefail
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
- # shellcheck source=dataops-common.sh
- source "${SCRIPT_DIR}/dataops-common.sh"
- PYTHON_BIN="${PYTHON_BIN:-python3}"
- RECREATE_VENV="${RECREATE_VENV:-0}"
- check_python() {
- echo_step "检查 Python..."
- if ! command -v "${PYTHON_BIN}" >/dev/null 2>&1; then
- echo_error "${PYTHON_BIN} 未安装"
- exit 1
- fi
- echo_info "Python: $(${PYTHON_BIN} --version 2>&1)"
- if command -v apt-get >/dev/null 2>&1; then
- if ! dpkg -l 2>/dev/null | grep -q python3-venv; then
- echo_warn "安装 python3-venv / python3-pip..."
- apt-get update && apt-get install -y python3-venv python3-pip
- fi
- fi
- }
- check_supervisor_pkg() {
- echo_step "检查 Supervisor..."
- if ! command -v supervisord >/dev/null 2>&1; then
- if command -v apt-get >/dev/null 2>&1; then
- apt-get update && apt-get install -y supervisor
- systemctl enable supervisor
- systemctl start supervisor
- else
- echo_error "Supervisor 未安装"
- exit 1
- fi
- fi
- echo_info "Supervisor 已就绪"
- }
- create_directories() {
- echo_step "创建目录..."
- mkdir -p "${APP_DIR}" "${LOG_DIR}" /data/upload /data/archive /var/log/supervisor
- chown -R "${APP_USER}:${APP_GROUP}" "${APP_DIR}" "${LOG_DIR}" /data/upload /data/archive
- echo_info "应用目录: ${APP_DIR}"
- echo_info "日志目录: ${LOG_DIR}"
- }
- setup_env_file() {
- echo_step "配置环境变量..."
- ensure_env_file "${SCRIPT_DIR}"
- normalize_env_file
- load_env_file
- ensure_env_file_permissions
- }
- setup_venv() {
- echo_step "配置 Python 虚拟环境..."
- if [[ "${RECREATE_VENV}" == "1" && -d "${VENV_DIR}" ]]; then
- echo_warn "重建虚拟环境: ${VENV_DIR}"
- rm -rf "${VENV_DIR}"
- fi
- if [[ ! -d "${VENV_DIR}" ]]; then
- sudo -u "${APP_USER}" "${PYTHON_BIN}" -m venv "${VENV_DIR}"
- fi
- "${VENV_DIR}/bin/pip" install --upgrade pip
- if [[ ! -f "${APP_DIR}/requirements.txt" ]]; then
- echo_error "缺少 ${APP_DIR}/requirements.txt"
- exit 1
- fi
- "${VENV_DIR}/bin/pip" install -r "${APP_DIR}/requirements.txt"
- chown -R "${APP_USER}:${APP_GROUP}" "${VENV_DIR}"
- echo_info "依赖安装完成"
- }
- verify_app() {
- echo_step "验证应用..."
- load_env_file
- sudo -u "${APP_USER}" env APP_ENV_FILE="${ENV_FILE}" FLASK_ENV=production \
- bash -c "set -a; source <(sed 's/\\r$//' '${ENV_FILE}' | sed '1s/^\\xEF\\xBB\\xBF//'); set +a; cd '${APP_DIR}'; '${VENV_DIR}/bin/python' -c \"
- from app import create_app
- app = create_app()
- print('Flask 应用创建成功')
- print('蓝图:', list(app.blueprints.keys()))
- \"" || {
- echo_error "应用验证失败,请检查 ${ENV_FILE} 中的数据库/Neo4j 等配置"
- exit 1
- }
- echo_info "应用验证通过"
- }
- sync_ops_scripts() {
- echo_step "同步运维脚本..."
- mkdir -p "${APP_DIR}/scripts"
- install -m 755 "${SCRIPT_DIR}/run_dataops.sh" "${RUN_SCRIPT}"
- for script in deploy_dataops.sh start_dataops.sh stop_dataops.sh restart_dataops.sh dataops-common.sh; do
- if [[ -f "${SCRIPT_DIR}/${script}" ]]; then
- install -m 755 "${SCRIPT_DIR}/${script}" "${SCRIPTS_DIR}/${script}"
- fi
- done
- chown -R "${APP_USER}:${APP_GROUP}" "${SCRIPTS_DIR}"
- normalize_shell_scripts "${SCRIPTS_DIR}"
- ensure_run_script
- }
- start_application() {
- echo_step "启动应用..."
- supervisorctl restart "${APP_NAME}" 2>/dev/null || supervisorctl start "${APP_NAME}"
- sleep 8
- local status
- status="$(supervisorctl status "${APP_NAME}" | awk '{print $2}')"
- if [[ "${status}" == "RUNNING" ]]; then
- echo_info "应用已运行"
- supervisorctl status "${APP_NAME}"
- else
- echo_error "应用启动失败,状态: ${status}"
- echo_info "查看日志: tail -f ${SUPERVISOR_LOG}"
- exit 1
- fi
- }
- show_summary() {
- local app_port
- app_port="$(resolve_listen_port)"
- echo ""
- echo "=========================================="
- echo -e "${GREEN} 部署完成${NC}"
- echo "=========================================="
- echo " 应用目录: ${APP_DIR}"
- echo " 环境变量: ${ENV_FILE}"
- echo " 监听地址: ${LISTEN_HOST}:${app_port}"
- echo ""
- echo " 启动: sudo ${APP_DIR}/scripts/start_dataops.sh"
- echo " 停止: sudo ${APP_DIR}/scripts/stop_dataops.sh"
- echo " 重启: sudo ${APP_DIR}/scripts/restart_dataops.sh"
- echo " 健康: curl http://127.0.0.1:${app_port}/api/system/health"
- echo ""
- }
- main() {
- echo "=========================================="
- echo " DataOps Platform 部署脚本"
- echo "=========================================="
- require_root
- check_python
- check_supervisor_pkg
- create_directories
- setup_env_file
- ensure_wsgi "${SCRIPT_DIR}"
- setup_venv
- verify_app
- sync_ops_scripts
- load_env_file
- configure_supervisor
- start_application
- if ! health_check; then
- echo_error "部署完成但健康检查失败,请根据上方诊断信息排查"
- exit 1
- fi
- show_summary
- }
- main "$@"
|