fix: 修改一下生图的 bug
This commit is contained in:
+107
-27
@@ -1,11 +1,112 @@
|
||||
#!/bin/zsh
|
||||
# 双击本文件,或在终端执行:./start.command
|
||||
cd "$(dirname "$0")"
|
||||
cd "$(dirname "$0")" || exit 1
|
||||
PROJECT_DIR="$PWD"
|
||||
|
||||
BACKEND_HOST="127.0.0.1"
|
||||
BACKEND_PORT="8800"
|
||||
BACKEND_URL="http://${BACKEND_HOST}:${BACKEND_PORT}"
|
||||
STUDIO_URL="http://localhost:8900"
|
||||
RUNTIME_DIR="$PROJECT_DIR/data/runtime"
|
||||
INSTANCE_PID_FILE="$RUNTIME_DIR/start-command.pid"
|
||||
|
||||
# 由当前 start.command 管理的子进程。它们都在清理函数里按 PID 树结束,
|
||||
# 不扫描或误杀其他项目的 Python / Node 进程。
|
||||
BACKEND_PID=""
|
||||
STUDIO_PID=""
|
||||
WORKER_SUPERVISOR_PID=""
|
||||
COLLECTOR_WATCH_PID=""
|
||||
COLLECTOR_STAMP=""
|
||||
CLEANUP_DONE=false
|
||||
|
||||
stop_process_tree() {
|
||||
local pid="$1"
|
||||
local child
|
||||
[[ "$pid" == <-> ]] || return 0
|
||||
kill -0 "$pid" 2>/dev/null || return 0
|
||||
# 先停止子进程,避免 Worker 守护循环在父进程退出前重新拉起 Worker。
|
||||
for child in $(pgrep -P "$pid" 2>/dev/null); do
|
||||
stop_process_tree "$child"
|
||||
done
|
||||
kill -TERM "$pid" 2>/dev/null || true
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
[[ "$CLEANUP_DONE" == true ]] && return
|
||||
CLEANUP_DONE=true
|
||||
stop_process_tree "$BACKEND_PID"
|
||||
stop_process_tree "$STUDIO_PID"
|
||||
stop_process_tree "$WORKER_SUPERVISOR_PID"
|
||||
stop_process_tree "$COLLECTOR_WATCH_PID"
|
||||
[[ -n "$COLLECTOR_STAMP" ]] && rm -f "$COLLECTOR_STAMP" 2>/dev/null
|
||||
if [[ -f "$INSTANCE_PID_FILE" ]] && [[ "$(<"$INSTANCE_PID_FILE")" == "$$" ]]; then
|
||||
rm -f "$INSTANCE_PID_FILE"
|
||||
fi
|
||||
}
|
||||
|
||||
on_signal() {
|
||||
exit 0
|
||||
}
|
||||
|
||||
stop_previous_instance() {
|
||||
[[ -f "$INSTANCE_PID_FILE" ]] || return 0
|
||||
local previous_pid command cwd
|
||||
previous_pid="$(<"$INSTANCE_PID_FILE")"
|
||||
if [[ "$previous_pid" != <-> ]] || ! kill -0 "$previous_pid" 2>/dev/null; then
|
||||
rm -f "$INSTANCE_PID_FILE"
|
||||
return 0
|
||||
fi
|
||||
|
||||
command="$(ps -p "$previous_pid" -o command= 2>/dev/null)"
|
||||
cwd="$(lsof -a -p "$previous_pid" -d cwd -Fn 2>/dev/null | sed -n 's/^n//p' | head -n 1)"
|
||||
if [[ "$command" != *"start.command"* || "$cwd" != "$PROJECT_DIR" ]]; then
|
||||
echo "⚠️ 发现过期的启动记录,未匹配到本项目进程,已忽略。"
|
||||
rm -f "$INSTANCE_PID_FILE"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "检测到已有工具台实例(PID: $previous_pid),正在停止后重新启动…"
|
||||
stop_process_tree "$previous_pid"
|
||||
for _ in {1..50}; do
|
||||
kill -0 "$previous_pid" 2>/dev/null || break
|
||||
sleep 0.1
|
||||
done
|
||||
if kill -0 "$previous_pid" 2>/dev/null; then
|
||||
echo "⚠️ 旧实例未能停止;为避免启动重复 Worker,本次不启动新实例。"
|
||||
exit 1
|
||||
fi
|
||||
rm -f "$INSTANCE_PID_FILE"
|
||||
}
|
||||
|
||||
stop_unmanaged_project_workers() {
|
||||
# PID 文件只能管理此前由 start.command 拉起的实例;这里额外收敛曾被手动
|
||||
# 启动、但 cwd 明确属于当前项目的 Worker。绝不按 Python 名称做全局清理。
|
||||
local pid parent_pid command cwd parent_command parent_cwd
|
||||
for pid in $(pgrep -f 'server/worker\.py' 2>/dev/null); do
|
||||
command="$(ps -p "$pid" -o command= 2>/dev/null)"
|
||||
cwd="$(lsof -a -p "$pid" -d cwd -Fn 2>/dev/null | sed -n 's/^n//p' | head -n 1)"
|
||||
[[ "$command" == *"server/worker.py"* && "$cwd" == "$PROJECT_DIR" ]] || continue
|
||||
|
||||
parent_pid="$(ps -p "$pid" -o ppid= 2>/dev/null | tr -d ' ')"
|
||||
parent_command="$(ps -p "$parent_pid" -o command= 2>/dev/null)"
|
||||
parent_cwd="$(lsof -a -p "$parent_pid" -d cwd -Fn 2>/dev/null | sed -n 's/^n//p' | head -n 1)"
|
||||
echo "检测到遗留 Worker(PID: $pid),正在停止…"
|
||||
if [[ "$parent_command" == *"start.command"* && "$parent_cwd" == "$PROJECT_DIR" ]]; then
|
||||
# 这是脱离 PID 文件的旧守护循环;连同父进程停掉,避免它 2 秒后重拉 Worker。
|
||||
stop_process_tree "$parent_pid"
|
||||
else
|
||||
# 手动启动的 Worker 只停止自身,不触碰其可能属于其他工具的父终端。
|
||||
kill -TERM "$pid" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
mkdir -p "$RUNTIME_DIR" || exit 1
|
||||
stop_previous_instance
|
||||
stop_unmanaged_project_workers
|
||||
print -r -- "$$" > "$INSTANCE_PID_FILE"
|
||||
trap cleanup EXIT
|
||||
trap on_signal INT TERM HUP
|
||||
|
||||
if [[ ! -d .venv ]]; then
|
||||
echo "未找到 .venv,正在创建…"
|
||||
@@ -32,7 +133,6 @@ fi
|
||||
|
||||
# ---- 采集插件(extensions/collector):启动时构建一次,之后监听代码改动自动重建 ----
|
||||
# 产物 .output/chrome-mv3 由 Chrome 以解压方式加载;重建后仍需去 chrome://extensions 点刷新
|
||||
COLLECTOR_WATCH_PID=""
|
||||
COLLECTOR_STAMP="$(mktemp -u /tmp/osk-collector-stamp.XXXXXX)"
|
||||
watch_collector() {
|
||||
touch "$COLLECTOR_STAMP"
|
||||
@@ -68,29 +168,6 @@ else
|
||||
fi
|
||||
echo
|
||||
|
||||
# ---- 同步并启动前端(studio:Vite 开发服务器,/api 代理到后端 8800)----
|
||||
STUDIO_PID=""
|
||||
WORKER_SUPERVISOR_PID=""
|
||||
cleanup() {
|
||||
if [[ -n "$WORKER_SUPERVISOR_PID" ]] && kill -0 "$WORKER_SUPERVISOR_PID" 2>/dev/null; then
|
||||
# 先终止 Worker 子进程,再结束守护循环;避免退出 start.command 后残留处理器。
|
||||
pkill -P "$WORKER_SUPERVISOR_PID" 2>/dev/null
|
||||
kill "$WORKER_SUPERVISOR_PID" 2>/dev/null
|
||||
fi
|
||||
if [[ -n "$STUDIO_PID" ]] && kill -0 "$STUDIO_PID" 2>/dev/null; then
|
||||
kill "$STUDIO_PID" 2>/dev/null
|
||||
sleep 0.2
|
||||
# 兜底:确保 vite 及其子进程退出
|
||||
lsof -ti :8900 | xargs kill 2>/dev/null
|
||||
fi
|
||||
if [[ -n "$COLLECTOR_WATCH_PID" ]] && kill -0 "$COLLECTOR_WATCH_PID" 2>/dev/null; then
|
||||
pkill -P "$COLLECTOR_WATCH_PID" 2>/dev/null # 可能正在跑的 build 子进程
|
||||
kill "$COLLECTOR_WATCH_PID" 2>/dev/null
|
||||
fi
|
||||
rm -f "$COLLECTOR_STAMP" 2>/dev/null
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
# ---- 持久化后台任务 Worker(与 uvicorn 独立,服务重启不会中断正在轮询的模型任务)----
|
||||
# Worker 因配置/网络等未捕获错误退出时,2 秒后自动拉起;否则任务会长期停在「排队中」。
|
||||
supervise_worker() {
|
||||
@@ -124,8 +201,11 @@ echo
|
||||
echo "按 Ctrl+C 可停止全部服务"
|
||||
echo
|
||||
|
||||
# --app-dir server 让 uvicorn 在 server/ 下找 main:app,工作目录仍是仓库根(.env 在此)
|
||||
uvicorn main:app --app-dir server --reload --reload-include '*.yaml' --host "$BACKEND_HOST" --port "$BACKEND_PORT"
|
||||
# --app-dir server 让 uvicorn 在 server/ 下找 main:app,工作目录仍是仓库根(.env 在此)。
|
||||
# 后端改为后台子进程 + wait:start.command 本身始终存活,PID 文件和 EXIT 清理才能可靠生效。
|
||||
uvicorn main:app --app-dir server --reload --reload-include '*.yaml' --host "$BACKEND_HOST" --port "$BACKEND_PORT" &
|
||||
BACKEND_PID=$!
|
||||
wait "$BACKEND_PID"
|
||||
|
||||
echo
|
||||
echo "服务已停止。按回车关闭窗口…"
|
||||
|
||||
Reference in New Issue
Block a user