Files
wehub-resource-sync 2114b14ee0
Sync main into demo / sync (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:35:26 +08:00

154 lines
5.1 KiB
Bash
Executable File

#!/bin/bash
# ============================================================
# mobile-gym 生产环境一键启动 (Nginx + API backend)
#
# 架构:
# Nginx (:PORT) ──┬── 静态文件 (dist/) ← sendfile 零拷贝
# └── /api/gw/* → Python (:PORT+1)
#
# 使用:
# ./scripts/server/start_nginx_gateway.sh # 默认 4180
# ./scripts/server/start_nginx_gateway.sh 4185 # 自定义端口
# ./scripts/server/start_nginx_gateway.sh stop # 停止
# ============================================================
PORT=${1:-4180}
API_PORT=$((PORT + 1))
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
ROOT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
cd "$ROOT_DIR" || exit 1
find_bin() {
local names=("$@")
# 1. Try command -v for each candidate name
for name in "${names[@]}"; do
local found
found="$(command -v "$name" 2>/dev/null)"
if [ -n "$found" ]; then echo "$found"; return; fi
done
# 2. conda / well-known fallback
for name in "${names[@]}"; do
local dir
for dir in \
"${CONDA_PREFIX:-}" \
"${CONDA_EXE%/bin/conda}" \
"$HOME/miniconda3" \
"$HOME/anaconda3" \
"$HOME/miniforge3"; do
[ -n "$dir" ] && [ -x "$dir/bin/$name" ] && { echo "$dir/bin/$name"; return; }
done
done
echo "[error] Cannot find '${names[*]}'. Install it or set ${names[0]^^}_BIN." >&2
exit 1
}
NGINX_BIN="${NGINX_BIN:-$(find_bin nginx)}"
NGINX_DIR="$ROOT_DIR/.nginx"
PIDFILE_API="$ROOT_DIR/.api_gateway.pid"
NGINX_SOURCE_CONFIG="$ROOT_DIR/.nginx/nginx.source.conf"
escape_sed_replacement() {
printf '%s' "$1" | sed -e 's/[\/&]/\\&/g'
}
render_nginx_config() {
local output="$NGINX_DIR/nginx.run.conf"
if [ ! -f "$NGINX_SOURCE_CONFIG" ]; then
echo "[error] Missing nginx source config: $NGINX_SOURCE_CONFIG" >&2
exit 1
fi
local esc_nginx_dir esc_mime_types esc_root
esc_nginx_dir="$(escape_sed_replacement "$NGINX_DIR")"
esc_mime_types="$(escape_sed_replacement "$MIME_TYPES")"
esc_root="$(escape_sed_replacement "$ROOT_DIR")"
sed \
-e "s/__NGINX_DIR__/$esc_nginx_dir/g" \
-e "s/__MIME_TYPES__/$esc_mime_types/g" \
-e "s/__ROOT__/$esc_root/g" \
-e "s/__PORT__/$PORT/g" \
-e "s/__API_PORT__/$API_PORT/g" \
"$NGINX_SOURCE_CONFIG" > "$output"
}
stop_servers() {
echo "[stop] Stopping servers..."
# Stop Nginx
if [ -f "$NGINX_DIR/nginx.pid" ]; then
"$NGINX_BIN" -s stop -c "$NGINX_DIR/nginx.run.conf" 2>/dev/null
echo " nginx stopped"
fi
# Stop API backend (kill process group for clean shutdown)
if [ -f "$PIDFILE_API" ]; then
local pid
pid="$(cat "$PIDFILE_API")"
kill -- "-$pid" 2>/dev/null || kill "$pid" 2>/dev/null
echo " api stopped"
rm -f "$PIDFILE_API"
fi
}
if [ "$1" = "stop" ]; then
stop_servers
exit 0
fi
# Stop any previous instances
stop_servers
# Create dirs
mkdir -p "$NGINX_DIR"/{logs,temp,ssl}
# Auto-generate self-signed TLS certificate for HTTP/2 (one-time)
if [ ! -f "$NGINX_DIR/ssl/localhost.crt" ]; then
echo "[setup] Generating self-signed TLS certificate for HTTP/2..."
if ! openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout "$NGINX_DIR/ssl/localhost.key" \
-out "$NGINX_DIR/ssl/localhost.crt" \
-subj '/CN=localhost'; then
echo "[error] Failed to generate TLS certificate. Is openssl installed?" >&2
exit 1
fi
echo " cert: $NGINX_DIR/ssl/localhost.crt"
fi
# Generate Nginx config
MIME_TYPES="$NGINX_DIR/mime.types"
if [ ! -f "$MIME_TYPES" ]; then
for p in \
"$(dirname "$NGINX_BIN")/../etc/nginx/mime.types" \
"/etc/nginx/mime.types"; do
if [ -f "$p" ]; then cp "$p" "$MIME_TYPES"; break; fi
done
fi
render_nginx_config
# 1. Start API backend (uvicorn multi-worker via conda rllm)
PYTHON_BIN="${PYTHON_BIN:-$(find_bin python python3)}"
API_WORKERS=${API_WORKERS:-8}
echo "[start] API gateway on :${API_PORT} (workers=${API_WORKERS})"
# setsid 在 Linux 上给 API gateway 起独立进程组,便于 stop 时 kill -- "-$pid" 一次清理 uvicorn 全家。
# macOS 默认没有 setsid,退回 nohup(同样能脱离终端 SIGHUP);stop_servers 里的 `|| kill "$pid"` 会兜底。
if command -v setsid >/dev/null 2>&1; then
setsid "$PYTHON_BIN" "$SCRIPT_DIR/api_gateway.py" --port "$API_PORT" --workers "$API_WORKERS" \
>> "$NGINX_DIR/logs/api_gateway.log" 2>&1 &
else
nohup "$PYTHON_BIN" "$SCRIPT_DIR/api_gateway.py" --port "$API_PORT" --workers "$API_WORKERS" \
>> "$NGINX_DIR/logs/api_gateway.log" 2>&1 &
fi
echo $! > "$PIDFILE_API"
# 2. Start Nginx
echo "[start] Nginx on :${PORT} (workers=8)"
"$NGINX_BIN" -c "$NGINX_DIR/nginx.run.conf"
sleep 0.5
echo ""
echo "✅ mobile-gym serving at https://0.0.0.0:${PORT} (HTTP/2 + TLS)"
echo " Static: Nginx (sendfile + HTTP/2 + 8 workers)"
echo " API: uvicorn + starlette (:${API_PORT}, ${API_WORKERS} workers)"
echo ""
echo " Stop: $0 stop"
echo " Logs: $NGINX_DIR/logs/{error,access,api_gateway}.log"