Files
huajishe-tts/run.sh
e2hang 0b14f7831d fix(run.sh): 修复退出清理——进程组杀法彻底回收 server/web 子进程
- server / web 均用 setsid 独立进程组,Ctrl-C 时 kill -TERM -PID 整组回收,
  避免 tsx watch / vite 派生的 node 子进程残留占用 8000 / 5173
- cleanup 改用 PIDS 数组,跳过空 PID,修正原版 WEB_PID 空串导致 kill 接空参的问题
- server 进程意外退出(如端口占用)时立即失败退出,不再傻等 web
- 端口行为保持原样:用户访问 :5173(vite),:8000 为内部 server
2026-08-25 18:29:21 +08:00

119 lines
3.9 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# tts-like 一键启动脚本
#
# 用法: ./run.sh
# 或: bash run.sh
#
# 行为:
# 1. 加载 nvm + 启用 pnpm每台机器首次跑会自动配好
# 2. node_modules 缺失时自动 pnpm install
# 3. 后台启动 boardgame.io relay server:8000
# 4. 前台启动 vite dev:5173
# 5. Ctrl-C 一起干净退出
#
# 启动后打开 http://localhost:5173
set -euo pipefail
# ---------- 1. 加载 nvm + pnpm ----------
export NVM_DIR="$HOME/.nvm"
if [ -s "$NVM_DIR/nvm.sh" ]; then
# shellcheck disable=SC1091
. "$NVM_DIR/nvm.sh"
fi
# 没有 node 直接报错(提示装 nvm
if ! command -v node >/dev/null 2>&1; then
echo "✗ 未找到 node。请先装 nvm + Node 22"
echo " curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash"
echo " nvm install 22"
exit 1
fi
NODE_VERSION=$(node -v)
echo "✓ node $NODE_VERSION"
# 启用 pnpmcorepack 是 Node 自带)
if ! command -v pnpm >/dev/null 2>&1; then
echo "→ 启用 pnpm (corepack)..."
corepack enable >/dev/null 2>&1 || true
fi
echo "✓ pnpm $(pnpm --version)"
# 切到项目根目录(脚本所在目录)
cd "$(dirname "$0")"
# ---------- 2. 依赖检查 ----------
if [ ! -d node_modules ]; then
echo "→ 首次运行,安装依赖(可能要 1-2 分钟)..."
pnpm install
fi
echo "✓ 依赖就绪"
# ---------- 3. 清理可能残留的旧进程 ----------
# 端口 8000 / 5173 若被占用会启动失败,这里只做提示
for port in 8000 5173; do
if command -v ss >/dev/null 2>&1 && ss -ltn "sport = :$port" 2>/dev/null | grep -q ":$port"; then
echo "⚠ 端口 $port 已被占用可能导致启动失败。如需清理lsof -ti:$port | xargs kill"
fi
done
# ---------- 4. 后台启动 server ----------
echo ""
echo "→ 启动 boardgame.io server (:8000)..."
setsid pnpm --filter @tts-like/server dev &
SERVER_PID=$!
PIDS=("$SERVER_PID")
WEB_PID=""
# 5. 退出时一起杀掉 server / web
cleanup() {
echo ""
echo "→ 退出,清理子进程..."
# 用进程组杀法,确保 tsx watch 派生的 node 子进程也一并退出(否则会残留占用端口)
for pid in "${PIDS[@]:-}"; do
[ -n "$pid" ] || continue
kill -TERM -"$pid" 2>/dev/null || kill "$pid" 2>/dev/null || true
done
for pid in "${PIDS[@]:-}"; do
[ -n "$pid" ] && kill -9 "$pid" 2>/dev/null || true
done
wait 2>/dev/null || true
echo "✓ 已退出"
}
trap cleanup EXIT INT TERM
# 等 server 起来(最多 15 秒,看到 listening 才继续)
echo "→ 等待 server 就绪..."
for i in $(seq 1 30); do
if curl -sf http://localhost:8000/healthz >/dev/null 2>&1; then
echo "✓ server 就绪"
break
fi
# server 进程已退出(如端口被占用崩溃)→ 直接失败退出,避免傻等
if ! kill -0 "$SERVER_PID" 2>/dev/null; then
echo "✗ server 进程已退出,启动失败。检查上方日志(常见于 :8000 端口被占用)。"
exit 1
fi
sleep 0.5
done
# ---------- 6. 前台启动 web ----------
echo ""
echo "════════════════════════════════════════════════════════════════"
echo " tts-like 已启动"
echo " Web: http://localhost:5173"
echo " Server: http://localhost:8000 (REST /api, WebSocket /socket.io)"
echo " 健康: http://localhost:8000/healthz"
echo ""
echo " 局域网其它设备访问: http://<本机内网IP>:5173/"
echo " Ctrl-C 一起退出"
echo "════════════════════════════════════════════════════════════════"
echo ""
# 前台跑 viteCtrl-C 会同时打到前台进程组web 退出后 trap 清理 server
setsid pnpm --filter @tts-like/web dev &
WEB_PID=$!
PIDS+=("$WEB_PID")
wait "$WEB_PID" 2>/dev/null || true