#!/usr/bin/env bash set -euo pipefail # 一键启动 FastAPI 后端: # - 自动创建/复用虚拟环境(.venv) # - 自动安装 requirements.txt 依赖 # - 自动启动 uvicorn(默认开启 --reload) # # 用法示例: # ./run.sh # 默认 host=0.0.0.0 port=8000 env=dev reload=on # ./run.sh --env prod # 使用 .env.prod(若存在且可被 source) # ./run.sh --port 9000 # 改端口 # ./run.sh --no-reload # 关闭热更新 # ./run.sh --install-only # 只安装依赖,不启动 usage() { cat <<'EOF' 用法: ./run.sh [--env dev|prod] [--host 0.0.0.0] [--port 8000] [--no-reload] [--skip-install] [--install-only] 参数: --env dev|prod 优先尝试加载 .env.dev 或 .env.prod(如果存在)。 --host uvicorn host(默认 0.0.0.0) --port uvicorn port(默认 8000) --no-reload 关闭 uvicorn --reload --skip-install 跳过依赖安装(默认会安装/更新 requirements.txt) --install-only 只安装依赖,不启动服务 -h, --help 显示帮助 说明: - 若你的 .env.* 不是 shell 可 source 的格式(例如包含空格/特殊字符未加引号),建议改成 KEY=value 形式。 - 启动后访问: /healthz 健康检查 /docs OpenAPI 文档 EOF } # 始终从脚本所在目录运行(避免在别处执行导致路径错) SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" cd "$SCRIPT_DIR" ENV_NAME="dev" HOST="0.0.0.0" PORT="8000" RELOAD="1" SKIP_INSTALL="0" INSTALL_ONLY="0" while [[ $# -gt 0 ]]; do case "$1" in --env) ENV_NAME="${2:-}" shift 2 ;; --host) HOST="${2:-}" shift 2 ;; --port) PORT="${2:-}" shift 2 ;; --no-reload) RELOAD="0" shift 1 ;; --skip-install) SKIP_INSTALL="1" shift 1 ;; --install-only) INSTALL_ONLY="1" shift 1 ;; -h|--help) usage exit 0 ;; *) echo "未知参数:$1" >&2 echo "" >&2 usage >&2 exit 2 ;; esac done if [[ "$ENV_NAME" != "dev" && "$ENV_NAME" != "prod" ]]; then echo "--env 仅支持 dev 或 prod,当前:$ENV_NAME" >&2 exit 2 fi ENV_FILE=".env.${ENV_NAME}" if [[ -f "$ENV_FILE" ]]; then # 让 source 进来的变量自动 export(供 pydantic-settings/应用读取) set -a # shellcheck disable=SC1090 source "$ENV_FILE" set +a fi # 选择 python 命令(优先 python3) PY_BIN="" if command -v python3 >/dev/null 2>&1; then PY_BIN="python3" elif command -v python >/dev/null 2>&1; then PY_BIN="python" else echo "未找到 python/python3,请先安装 Python 3.11+。" >&2 exit 1 fi VENV_DIR=".venv" if [[ ! -d "$VENV_DIR" ]]; then echo "创建虚拟环境:$VENV_DIR" "$PY_BIN" -m venv "$VENV_DIR" fi # 激活虚拟环境 # shellcheck disable=SC1091 source "$VENV_DIR/bin/activate" if [[ "$SKIP_INSTALL" == "0" ]]; then if [[ -f "requirements.txt" ]]; then echo "升级 pip 并安装依赖(requirements.txt)" python -m pip install -U pip python -m pip install -r requirements.txt else echo "未找到 requirements.txt,跳过依赖安装。" >&2 fi fi if [[ "$INSTALL_ONLY" == "1" ]]; then echo "依赖安装完成(install-only),退出。" exit 0 fi UVICORN_ARGS=(app.main:app --host "$HOST" --port "$PORT") if [[ "$RELOAD" == "1" ]]; then UVICORN_ARGS+=(--reload) fi echo "启动服务:uvicorn ${UVICORN_ARGS[*]}" exec uvicorn "${UVICORN_ARGS[@]}"