Files
AgentLab/scripts/dev.sh
T
ThearchyHelios 80ac1d9c88 dev.sh 支持 --host:前端在局域网上也能打开;认不出的参数直接报错
- 以前 dev.sh 不读任何参数,./scripts/dev.sh --host 被悄悄忽略,前端照旧只听本机
- --host 让前端开发服务器监听所有网卡,启动时打印局域网地址;后端仍只听 127.0.0.1,
  页面里的 /api 由前端开发服务器在本机转发,局域网里的设备不需要、也不该直连后端
- 用法说明里写明:AgentLab 没有登录,同一网络里打得开页面的人都能用它,只在信得过的网络里开
- 认不出的参数报错并打印用法(-h / --help 看用法)
2026-09-29 17:28:34 +08:00

107 lines
4.4 KiB
Bash
Executable File
Raw 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
# 一条命令把前后端都拉起来。Ctrl-C 一起退出。
set -euo pipefail
usage() {
cat <<'USAGE'
用法:./scripts/dev.sh [--host]
--host 前端也在局域网上监听(同一网络里的手机、别的电脑能打开)。后端仍只听 127.0.0.1:
页面里的 /api 由前端开发服务器在本机转发,局域网里的设备不需要、也不该直连后端。
注意:AgentLab 没有登录,同一网络里打得开页面的人都能用它——跑工作流、花你配的
模型额度、读数据源、执行沙箱代码。只在信得过的网络里开。
USAGE
}
# 参数先认完再干活:以前不读参数,--host 这类写了也被悄悄忽略
WEB_ARGS=()
for arg in "$@"; do
case "$arg" in
--host) WEB_ARGS+=(--host) ;;
-h|--help) usage; exit 0 ;;
*) echo "认不出的参数:$arg"; echo; usage; exit 2 ;;
esac
done
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
API_PORT="${AGENTLAB_PORT:-8000}"
WEB_PORT="${AGENTLAB_WEB_PORT:-5273}"
CONDA_ENV="${AGENTLAB_CONDA_ENV:-agentlab}"
command -v conda >/dev/null || { echo "缺少 conda:https://conda-forge.org/miniforge/"; exit 1; }
command -v pnpm >/dev/null || { echo "缺少 pnpm:npm i -g pnpm"; exit 1; }
# 环境不存在就按 environment.yml 建一个
if ! conda env list | awk '{print $1}' | grep -qx "$CONDA_ENV"; then
echo "==> 创建 conda 环境 $CONDA_ENV"
conda env create -f "$ROOT/environment.yml"
fi
PY_BIN="$(conda run -n "$CONDA_ENV" python -c 'import sys; print(sys.executable)' 2>/dev/null)"
[ -x "$PY_BIN" ] || { echo "conda 环境 $CONDA_ENV 不可用,试试:conda env create -f environment.yml"; exit 1; }
echo "==> 后端解释器 $PY_BIN"
[ -d "$ROOT/frontend/node_modules" ] || (cd "$ROOT/frontend" && pnpm install)
# 端口被别人占着就往后挪。踩过一次坑:8000 被另一个项目占住时,uvicorn
# 起不来直接退出,而下面的健康检查去探 8000 又被那个项目答应了,脚本以为
# 后端就绪、继续起前端——于是前端连着别人的服务,界面显示的全是陈年旧数据。
port_taken() { lsof -nP -iTCP:"$1" -sTCP:LISTEN >/dev/null 2>&1; }
if [ -z "${AGENTLAB_PORT:-}" ]; then
while port_taken "$API_PORT"; do
echo "==> 端口 $API_PORT 已被占用,换 $((API_PORT + 1))"
API_PORT=$((API_PORT + 1))
done
elif port_taken "$API_PORT"; then
echo "端口 $API_PORT 已被占用(AGENTLAB_PORT 指定的),换一个或停掉占用方"
lsof -nP -iTCP:"$API_PORT" -sTCP:LISTEN | tail -n +2 | head -3
exit 1
fi
# 前端代理要跟着后端端口走,否则请求会打到占端口的那个服务上
export AGENTLAB_PORT="$API_PORT"
cleanup() {
echo
echo "==> 停止"
# 杀掉整个进程组,避免 uvicorn / vite 变成孤儿进程
[ -n "${API_PID:-}" ] && kill "$API_PID" 2>/dev/null || true
[ -n "${WEB_PID:-}" ] && kill "$WEB_PID" 2>/dev/null || true
wait 2>/dev/null || true
}
trap cleanup EXIT INT TERM
echo "==> 后端 http://127.0.0.1:$API_PORT"
(cd "$ROOT/backend" && "$PY_BIN" -m uvicorn app.main:app --host 127.0.0.1 --port "$API_PORT" --reload) &
API_PID=$!
# 等后端起来再起前端,省得前端第一次请求就打空。
# 光看"有没有响应"不够——得确认答应的是 agentlab 自己,不是碰巧占着
# 这个端口的别的服务;顺便看住后端进程别悄悄死了。
ready=""
for _ in $(seq 1 60); do
if ! kill -0 "$API_PID" 2>/dev/null; then
echo "后端启动失败,上面应该有它的报错"
exit 1
fi
if curl -sf "http://127.0.0.1:$API_PORT/api/health" 2>/dev/null | grep -q '"agentlab"'; then
ready=1; break
fi
sleep 0.5
done
[ -n "$ready" ] || { echo "后端 30s 内没就绪(或 $API_PORT 上答话的不是 agentlab)"; exit 1; }
echo "==> 前端 http://localhost:$WEB_PORT"
(cd "$ROOT/frontend" && pnpm dev --port "$WEB_PORT" ${WEB_ARGS[@]+"${WEB_ARGS[@]}"}) &
WEB_PID=$!
echo
echo " 界面 http://localhost:$WEB_PORT"
if [ ${#WEB_ARGS[@]} -gt 0 ]; then
# 本机在局域网里的地址:macOS 取 en0 / en1,Linux 取 hostname -I 的第一个
LAN_IP="$(ipconfig getifaddr en0 2>/dev/null || ipconfig getifaddr en1 2>/dev/null || hostname -I 2>/dev/null | awk '{print $1}' || true)"
echo " 局域网 http://${LAN_IP:-<本机 IP>}:$WEB_PORT (没有登录:同一网络里打得开页面的人都能用它)"
fi
echo " 接口 http://127.0.0.1:$API_PORT/docs"
echo
wait