digital-embryo/start-dev.sh
2025-11-09 19:37:39 +08:00

192 lines
4.8 KiB
Bash
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
set -Eeuo pipefail
echo -e "\033[32m正在启动 Digital Embryo 开发环境...\033[0m"
# 获取当前脚本所在目录
SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
# 前后端目录
FRONTEND_DIR="${SCRIPT_DIR}/embryo-frontend"
BACKEND_DIR="${SCRIPT_DIR}/embryo-backend"
# 颜色输出
yellow() { echo -e "\033[33m$*\033[0m"; }
green() { echo -e "\033[32m$*\033[0m"; }
cyan() { echo -e "\033[36m$*\033[0m"; }
red() { echo -e "\033[31m$*\033[0m"; }
# PATH 修正助手
prepend_path_if_dir_exists() {
local dir="$1"
if [[ -d "$dir" ]] && [[ ":$PATH:" != *":${dir}:"* ]]; then
export PATH="${dir}:${PATH}"
fi
}
# 确保 brew 可用(不强制安装,避免交互)
has_brew() { command -v brew >/dev/null 2>&1; }
# 安装 npm优先 brew其次 nvm
ensure_npm() {
if command -v npm >/dev/null 2>&1; then
return 0
fi
yellow "未检测到 npm尝试自动安装..."
if has_brew; then
yellow "使用 Homebrew 安装 Node.js包含 npm..."
if brew install node; then
green "已通过 Homebrew 安装 Node.js/npm"
return 0
else
red "通过 Homebrew 安装 Node.js 失败,回退到 nvm 安装方式"
fi
fi
# 回退:安装 nvm 并安装 Node LTS
yellow "安装 nvm..."
export NVM_DIR="$HOME/.nvm"
mkdir -p "$NVM_DIR"
if curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash; then
# 当前会话加载 nvm
if [[ -s "$NVM_DIR/nvm.sh" ]]; then
# shellcheck disable=SC1090
. "$NVM_DIR/nvm.sh"
fi
if [[ -s "$NVM_DIR/bash_completion" ]]; then
# shellcheck disable=SC1090
. "$NVM_DIR/bash_completion"
fi
yellow "使用 nvm 安装 Node.js LTS..."
nvm install --lts
nvm use --lts
nvm alias default 'lts/*' || true
else
red "安装 nvm 失败"
fi
if ! command -v npm >/dev/null 2>&1; then
red "自动安装 npm 失败,请手动安装 Node.js/npm 后重试。"
exit 1
fi
green "npm 安装完成"
}
# 安装 uv优先 brew其次官方脚本
ensure_uv() {
if command -v uv >/dev/null 2>&1; then
return 0
fi
yellow "未检测到 uv尝试自动安装..."
if has_brew; then
yellow "使用 Homebrew 安装 uv..."
if brew install uv; then
green "已通过 Homebrew 安装 uv"
return 0
else
red "通过 Homebrew 安装 uv 失败,回退到官方安装脚本"
fi
fi
# 回退:官方安装脚本(将二进制置于 ~/.local/bin 或 ~/.cargo/bin
if curl -fsSL https://astral.sh/uv/install.sh | sh; then
# 尝试将常见安装目录加入 PATH仅当前会话
prepend_path_if_dir_exists "$HOME/.local/bin"
prepend_path_if_dir_exists "$HOME/.cargo/bin"
else
red "运行 uv 官方安装脚本失败"
fi
if ! command -v uv >/dev/null 2>&1; then
red "自动安装 uv 失败,请手动安装 uv 后重试(可用 brew install uv。"
exit 1
fi
green "uv 安装完成"
}
# 基础校验
if [[ ! -d "${FRONTEND_DIR}" ]]; then
echo "前端目录不存在: ${FRONTEND_DIR}" >&2
exit 1
fi
if [[ ! -d "${BACKEND_DIR}" ]]; then
echo "后端目录不存在: ${BACKEND_DIR}" >&2
exit 1
fi
PACKAGE_JSON_PATH="${FRONTEND_DIR}/package.json"
APP_PY_PATH="${BACKEND_DIR}/app.py"
if [[ ! -f "${PACKAGE_JSON_PATH}" ]]; then
echo "package.json 文件不存在: ${PACKAGE_JSON_PATH}" >&2
exit 1
fi
if [[ ! -f "${APP_PY_PATH}" ]]; then
echo "app.py 文件不存在: ${APP_PY_PATH}" >&2
exit 1
fi
# 依赖校验与自动安装
ensure_npm
ensure_uv
echo -e "\033[33m启动前端开发服务器...\033[0m"
pushd "${FRONTEND_DIR}" >/dev/null
npm run dev &
FRONTEND_PID=$!
popd >/dev/null
echo -e "\033[33m启动后端API服务器...\033[0m"
pushd "${SCRIPT_DIR}" >/dev/null
uv run "${BACKEND_DIR}/app.py" &
BACKEND_PID=$!
popd >/dev/null
echo -e "\033[32m两个服务都已启动!\033[0m"
echo -e "\033[36m前端开发服务器通常运行在: http://localhost:5173\033[0m"
echo -e "\033[36m后端API服务器通常运行在: http://localhost:5000\033[0m"
echo
echo -e "\033[31m按 Ctrl+C 停止所有服务\033[0m"
cleanup() {
echo -e "\033[33m正在停止所有服务...\033[0m"
if ps -p ${FRONTEND_PID} >/dev/null 2>&1; then
kill ${FRONTEND_PID} 2>/dev/null || true
wait ${FRONTEND_PID} 2>/dev/null || true
fi
if ps -p ${BACKEND_PID} >/dev/null 2>&1; then
kill ${BACKEND_PID} 2>/dev/null || true
wait ${BACKEND_PID} 2>/dev/null || true
fi
echo -e "\033[32m所有服务已停止\033[0m"
}
trap cleanup INT TERM
# 监控:若任一服务退出则结束脚本并清理
while true; do
if ! ps -p ${FRONTEND_PID} >/dev/null 2>&1; then
echo "前端服务已退出"
break
fi
if ! ps -p ${BACKEND_PID} >/dev/null 2>&1; then
echo "后端服务已退出"
break
fi
sleep 1
done
cleanup
exit 0