- 迁移 → 管理员初始化 → 前端构建 → API+worker 后台启动 → 健康检查 → 自动打开页面
- 支持 --stop 停止、--no-open 跳过打开浏览器;端口已在服务时直接复用
- 未设 DATABASE_URL 时使用 SQLite 轻量库并给出验收提示
- 修复 bash 3.2(macOS 自带)将紧贴 $VAR 的多字节字符并入变量名的问题:
全角括号内的变量一律用 ${VAR} 显式界定
- README 本地运行章节补充快速启动说明
This commit is contained in:
Executable
+124
@@ -0,0 +1,124 @@
|
||||
#!/usr/bin/env bash
|
||||
# 一键启动本地开发环境:迁移 → 初始化管理员 → 构建前端 → 启动 API+worker → 打开页面。
|
||||
# 默认使用 SQLite 轻量开发库(var/db.sqlite3);设置 DATABASE_URL 则使用 PostgreSQL。
|
||||
# Ctrl-C 或 --stop 停止本脚本启动的进程。
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "$ROOT"
|
||||
|
||||
PORT="${PORT:-8000}"
|
||||
SERVER_PID_FILE="var/dev-server.pid"
|
||||
WORKER_PID_FILE="var/dev-worker.pid"
|
||||
SERVER_LOG="var/dev-server.log"
|
||||
WORKER_LOG="var/dev-worker.log"
|
||||
|
||||
die() { echo "错误:$*" >&2; exit 1; }
|
||||
|
||||
detect_python() {
|
||||
if [ -x ".venv/bin/python" ]; then
|
||||
PY=".venv/bin/python"
|
||||
elif command -v uv >/dev/null 2>&1; then
|
||||
PY="uv run python"
|
||||
else
|
||||
die "未找到 .venv/bin/python 或 uv,请先安装依赖(uv sync)"
|
||||
fi
|
||||
}
|
||||
|
||||
read_pidfile() { [ -f "$1" ] && cat "$1" || true; }
|
||||
|
||||
stop_all() {
|
||||
local stopped=0 pid
|
||||
for file in "$SERVER_PID_FILE" "$WORKER_PID_FILE"; do
|
||||
pid="$(read_pidfile "$file")"
|
||||
if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
|
||||
kill "$pid" 2>/dev/null || true
|
||||
stopped=1
|
||||
fi
|
||||
rm -f "$file"
|
||||
done
|
||||
[ "$stopped" = 1 ] && echo "已停止本地开发服务" || echo "没有正在运行的开发服务"
|
||||
}
|
||||
|
||||
health_ok() { curl -fsS --max-time 2 "http://127.0.0.1:$PORT/api/health" >/dev/null 2>&1; }
|
||||
|
||||
open_page() {
|
||||
local url="http://127.0.0.1:$PORT/"
|
||||
if command -v open >/dev/null 2>&1; then open "$url"
|
||||
elif command -v xdg-open >/dev/null 2>&1; then xdg-open "$url" >/dev/null 2>&1 || true
|
||||
fi
|
||||
}
|
||||
|
||||
case "${1:-}" in
|
||||
--stop)
|
||||
stop_all
|
||||
exit 0
|
||||
;;
|
||||
"" | --no-open) ;;
|
||||
*) die "未知参数:$1(支持 --stop / --no-open)" ;;
|
||||
esac
|
||||
|
||||
detect_python
|
||||
mkdir -p var
|
||||
|
||||
if health_ok; then
|
||||
echo "已在 $PORT 端口运行,直接打开页面"
|
||||
[ "${1:-}" != "--no-open" ] && open_page
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ -z "${DATABASE_URL:-}" ]; then
|
||||
echo "未设置 DATABASE_URL,使用 SQLite 轻量开发库 var/db.sqlite3(仅限页面测试与开发回归)"
|
||||
fi
|
||||
|
||||
echo "执行数据库迁移…"
|
||||
$PY manage.py migrate --no-input >/dev/null
|
||||
|
||||
if [ ! -f var/local-access.txt ]; then
|
||||
echo "初始化本地管理员…"
|
||||
PYTHONPATH="$ROOT" $PY scripts/init_local.py
|
||||
fi
|
||||
|
||||
if [ ! -d frontend/dist ]; then
|
||||
echo "构建前端(首次)…"
|
||||
npm run build >/dev/null
|
||||
fi
|
||||
|
||||
echo "启动 worker(日志 ${WORKER_LOG})…"
|
||||
nohup $PY manage.py import_worker >"$WORKER_LOG" 2>&1 &
|
||||
echo $! >"$WORKER_PID_FILE"
|
||||
|
||||
echo "启动 API 服务…"
|
||||
nohup $PY manage.py runserver "127.0.0.1:$PORT" --noreload >"$SERVER_LOG" 2>&1 &
|
||||
echo $! >"$SERVER_PID_FILE"
|
||||
|
||||
cleanup() {
|
||||
stop_all >/dev/null 2>&1 || true
|
||||
}
|
||||
trap cleanup INT TERM
|
||||
|
||||
for _ in $(seq 1 30); do
|
||||
if health_ok; then
|
||||
break
|
||||
fi
|
||||
if [ -n "$(read_pidfile "$SERVER_PID_FILE")" ] && ! kill -0 "$(read_pidfile "$SERVER_PID_FILE")" 2>/dev/null; then
|
||||
tail -20 "$SERVER_LOG" >&2
|
||||
die "API 服务启动失败(完整日志:${SERVER_LOG})"
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
health_ok || { tail -20 "$SERVER_LOG" >&2; die "健康检查超时(日志:${SERVER_LOG})"; }
|
||||
|
||||
echo
|
||||
echo "本地开发环境已就绪:http://127.0.0.1:$PORT"
|
||||
[ -f var/local-access.txt ] && echo "登录凭据:var/local-access.txt(用户名 admin,权限 0600)"
|
||||
if [ -z "${DATABASE_URL:-}" ]; then
|
||||
echo "提示:当前为 SQLite 轻量模式;高精度金额聚合与生产验收请按 README 配置 PostgreSQL。"
|
||||
fi
|
||||
echo "日志:${SERVER_LOG} / ${WORKER_LOG} · Ctrl-C 或 scripts/dev_up.sh --stop 停止"
|
||||
echo
|
||||
|
||||
[ "${1:-}" != "--no-open" ] && open_page
|
||||
|
||||
wait "$(read_pidfile "$SERVER_PID_FILE")" || true
|
||||
cleanup
|
||||
Reference in New Issue
Block a user