-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstart.sh
More file actions
executable file
·78 lines (71 loc) · 3.65 KB
/
Copy pathstart.sh
File metadata and controls
executable file
·78 lines (71 loc) · 3.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#!/usr/bin/env bash
# mcp-video-transcript 一键启动/重启。
# - 端口空闲 → 启动(优先经 launchd,保留开机自启 + 崩溃自愈)。
# - 端口被"本程序"占用 → 停掉旧实例(launchd bootout + kill)后重启。
# - 端口被"别的程序"占用 → 报错提醒,绝不动它。
# 判定"是不是本程序":该进程的当前工作目录 == 本仓库目录(launchd 与手动启动都满足)。
set -uo pipefail
REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LABEL="com.weft.video-transcript"
PLIST="$HOME/Library/LaunchAgents/$LABEL.plist"
GUI="gui/$(id -u)"
LOG="$HOME/Library/Logs/video-transcript.log"
PORT="$(sed -n 's/^[[:space:]]*port[[:space:]]*=[[:space:]]*\([0-9][0-9]*\).*/\1/p' "$REPO/config.toml" 2>/dev/null | head -1)"
PORT="${PORT:-8010}"
port_pids() { lsof -nP -iTCP:"$PORT" -sTCP:LISTEN -t 2>/dev/null; }
proc_cwd() { lsof -a -p "$1" -d cwd -Fn 2>/dev/null | sed -n 's/^n//p' | head -1; }
proc_cmd() { ps -p "$1" -o command= 2>/dev/null; }
is_ours() { [ "$(proc_cwd "$1")" = "$REPO" ] && return 0
proc_cmd "$1" | grep -q "server.py" && proc_cmd "$1" | grep -q "$REPO"; }
lan_ip() { # 本机局域网 IPv4:默认路由接口优先,回退扫 en0..en8;拿不到用 0.0.0.0
local ip="" iface
iface="$(route -n get default 2>/dev/null | awk '/interface:/{print $2}')"
[ -n "$iface" ] && ip="$(ipconfig getifaddr "$iface" 2>/dev/null)"
if [ -z "$ip" ]; then
for i in 0 1 2 3 4 5 6 7 8; do ip="$(ipconfig getifaddr "en$i" 2>/dev/null)"; [ -n "$ip" ] && break; done
fi
[ -n "$ip" ] && echo "$ip" || echo "0.0.0.0"
}
echo "▶ mcp-video-transcript 端口 $PORT 仓库 $REPO"
# 1) 端口占用检查:有"别的程序"占用就直接报错退出
PIDS="$(port_pids)"
for pid in $PIDS; do
if ! is_ours "$pid"; then
echo "✖ 端口 $PORT 被【其它程序】占用,已终止启动(不会动它):"
echo " PID $pid → $(proc_cmd "$pid")"
echo " 请自行处理该进程,或改 config.toml 里的 port。"
exit 1
fi
done
[ -n "$PIDS" ] && echo "⚠ 端口被本程序占用(PID: $PIDS),先停旧实例…"
# 2) 停:bootout(停 launchd 托管 + 阻止 KeepAlive 重生)→ 等 label 消失 → kill 残留 → 等端口释放
launchctl bootout "$GUI/$LABEL" 2>/dev/null
for i in $(seq 1 20); do launchctl list "$LABEL" >/dev/null 2>&1 || break; sleep 0.3; done
for pid in $PIDS; do kill "$pid" 2>/dev/null; done
for i in $(seq 1 24); do
[ -z "$(port_pids)" ] && break
[ "$i" = 14 ] && for pid in $(port_pids); do kill -9 "$pid" 2>/dev/null; done
sleep 0.5
done
if [ -n "$(port_pids)" ]; then echo "✖ 端口 $PORT 仍未释放,放弃。"; exit 1; fi
# 3) 启:装了 launchd 就用 launchd(开机自启 + 崩溃自愈);bootstrap 带重试(偶发 I/O error=上次 bootout 未 settle)
if [ -f "$PLIST" ]; then
echo "▶ 经 launchd 启动($LABEL)…"
ERR="/tmp/vt_bootstrap.$$"; ok=0
for i in $(seq 1 6); do
if launchctl bootstrap "$GUI" "$PLIST" 2>"$ERR"; then ok=1; break; fi
sleep 1
done
if [ "$ok" != 1 ]; then echo "✖ launchd bootstrap 失败:$(cat "$ERR" 2>/dev/null)"; rm -f "$ERR"; exit 1; fi
rm -f "$ERR"
else
echo "▶ launchd 未安装,后台直接启动…"
( cd "$REPO" && nohup ./venv/bin/python server.py --preload >>"$LOG" 2>&1 & )
fi
# 4) 等就绪(--preload 加载模型 ~7s,首次下模型更久),确认端口在监听
printf " 等待就绪"
for i in $(seq 1 90); do
if [ -n "$(port_pids)" ]; then echo " ✔"; echo "✅ 已就绪:http://$(lan_ip):$PORT/mcp (局域网地址;实际监听 0.0.0.0 全网卡) 日志:$LOG"; exit 0; fi
printf "."; sleep 1
done
echo " ⏱"; echo "⚠ 90s 内端口未监听,可能仍在下模型或启动失败,请看日志:$LOG"; exit 1