#!/usr/bin/env bash # 一键启动傻瓜比价本地联调:用户侧 API(8770) + 运营后台 API(8771) + 运营后台前端(3001)。 # 跨平台:Windows(Git Bash)与 macOS 通用。停止用 ./stop.sh。 # # 路径相对本脚本推导(本脚本在 shaguabijia-admin-web 内,server 是它的同级目录), # 不再写死绝对路径——两个仓库放在同一父目录下即可。 # # 可用环境变量覆盖: # SHAGUA_CONDA_ENV 指定 conda 环境名(默认自动从 shaguabijia-app-server / price 里挑) # NODE_DIR 指定含 node 的目录(默认自动探测;Windows 上找 ~/nodejs/node-v*-win-x64) # 不用 set -e:端口探测等命令正常会返回非零,逐步自己判错。 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" WEB_DIR="$SCRIPT_DIR" WORKSPACE="$(dirname "$SCRIPT_DIR")" SERVER_DIR="$WORKSPACE/shaguabijia-app-server" LOG_DIR="$SCRIPT_DIR/.run-logs" mkdir -p "$LOG_DIR" case "$(uname -s)" in MINGW* | MSYS* | CYGWIN*) IS_WIN=1 ;; *) IS_WIN=0 ;; esac # ---- 工具:端口占用判断 / 按端口杀进程(stop.sh 复用同款逻辑) ---- port_in_use() { local p="$1" if [ "$IS_WIN" = "1" ]; then netstat -ano 2>/dev/null | grep -E "[:.]$p[[:space:]].*LISTENING" >/dev/null 2>&1 else lsof -ti "tcp:$p" >/dev/null 2>&1 fi } # ---- 1. (仅 macOS + 有 brew + 后端用 PG 时) 尽力拉起 PostgreSQL;sqlite 下无需,失败不致命 ---- if [ "$IS_WIN" = "0" ] && command -v brew >/dev/null 2>&1; then if grep -qi "postgresql" "$SERVER_DIR/.env" 2>/dev/null; then brew services start postgresql@16 >/dev/null 2>&1 || true fi fi # ---- 2. 定位并激活 conda 环境 ---- CONDA_SH="" for c in "$HOME/miniconda3/etc/profile.d/conda.sh" "$HOME/anaconda3/etc/profile.d/conda.sh" \ "/c/Users/$USER/miniconda3/etc/profile.d/conda.sh" "/opt/homebrew/Caskroom/miniconda/base/etc/profile.d/conda.sh"; do [ -f "$c" ] && { CONDA_SH="$c"; break; } done [ -z "$CONDA_SH" ] && { echo "❌ 找不到 conda.sh,请确认装了 miniconda/anaconda"; exit 1; } # shellcheck disable=SC1090 source "$CONDA_SH" ENV="${SHAGUA_CONDA_ENV:-}" if [ -z "$ENV" ]; then for cand in shaguabijia-app-server price; do if conda env list | awk '{print $1}' | grep -qx "$cand"; then ENV="$cand"; break; fi done fi [ -z "$ENV" ] && { echo "❌ 没找到可用 conda 环境(试过 shaguabijia-app-server / price),用 SHAGUA_CONDA_ENV 指定"; exit 1; } conda activate "$ENV" || { echo "❌ conda activate $ENV 失败"; exit 1; } python -c "import uvicorn" 2>/dev/null || { echo "❌ 环境 '$ENV' 里没装 uvicorn,换个环境(SHAGUA_CONDA_ENV=...)再跑"; exit 1; } echo "🐍 conda 环境: $ENV" # ---- 3. 定位 node(已在 PATH 直接用;否则探测常见安装位) ---- if ! command -v node >/dev/null 2>&1; then CANDS=("$NODE_DIR") for g in "$HOME"/nodejs/node-v*-win-x64 "$HOME"/nodejs/node-v*-darwin-* "/c/Program Files/nodejs" "/usr/local/bin" "/opt/homebrew/bin"; do CANDS+=("$g") done for d in "${CANDS[@]}"; do [ -n "$d" ] || continue if [ -x "$d/node.exe" ] || [ -x "$d/node" ]; then export PATH="$d:$PATH"; break; fi done fi command -v node >/dev/null 2>&1 || { echo "❌ 找不到 node。装好后若仍找不到,用 NODE_DIR=<含 node 的目录> 指定"; exit 1; } echo "🟢 node: $(node -v)" echo "" # ---- 4. 起后端两个服务 + 前端;已在跑的端口跳过 ---- # 默认不加 --reload:reload 会派生「监督+工作」两进程,stop.sh 按 PID 只杀得掉监督、工作进程 # 仍占端口(Windows 上尤甚)。要热重载就 `RELOAD=1 bash start.sh`(届时改完代码用 stop.sh 可能 # 残留工作进程,需手动按端口清)。 RELOAD_FLAG="" [ "${RELOAD:-0}" = "1" ] && RELOAD_FLAG="--reload" start_uvicorn() { local name="$1" app="$2" port="$3" host="$4" if port_in_use "$port"; then echo "↺ $name 已在 :$port(跳过)"; return; fi cd "$SERVER_DIR" || exit 1 nohup python -m uvicorn "$app" --host "$host" --port "$port" $RELOAD_FLAG \ > "$LOG_DIR/$name.log" 2>&1 & echo "$!" > "$LOG_DIR/$name.pid" echo "✅ $name 起在 :$port (日志 $LOG_DIR/$name.log)" } # 用户侧绑 0.0.0.0,真机/模拟器可经局域网 IP 访问;后台只本机用,绑 127.0.0.1 start_uvicorn "user-api" "app.main:app" 8770 "0.0.0.0" start_uvicorn "admin-api" "app.admin.main:admin_app" 8771 "127.0.0.1" if port_in_use 3001; then echo "↺ admin-web 已在 :3001(跳过)" else cd "$WEB_DIR" || exit 1 nohup npm run dev > "$LOG_DIR/admin-web.log" 2>&1 & echo "$!" > "$LOG_DIR/admin-web.pid" echo "✅ admin-web 起在 :3001 (日志 $LOG_DIR/admin-web.log)" fi echo "" echo "⏳ 前端首次编译要几秒,然后开 👉 http://localhost:3001 (admin / admin12345)" echo " 用户侧 API: http://127.0.0.1:8770 | 后台 API: http://127.0.0.1:8771/admin/docs" echo " 看日志: tail -f $LOG_DIR/admin-web.log | 停止: bash \"$SCRIPT_DIR/stop.sh\""