Files
deploy-test/07-start-frontend.sh
2026-04-21 12:24:04 +07:00

264 lines
7.8 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
# =============================================================================
# 07-start-frontend.sh — 启动前端开发服务器(开发态)
#
# 用法:
# ./07-start-frontend.sh # 启动全部前端项目
# ./07-start-frontend.sh <project> # 只启动指定项目
#
# 项目与端口:
# meetingh5 → Vue + Vite :5188
# h5 → Vue + Vite :3003
#
#
# 注意:
# pc / cms / build-cms / build-down 已改为静态构建 + Nginx 域名访问:
# ./deploy-test/08-build-static-frontend.sh
#
# 日志文件: .local-dev/logs/fe-<project>.log
# PID 文件: .local-dev/pids/fe-<project>.pid
# =============================================================================
set -euo pipefail
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common.sh"
init_dirs
SCRIPT_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/$(basename "${BASH_SOURCE[0]}")"
# 供文末打印访问地址set -u 下须已定义;与 01-init-env 中 DEPLOY_TEST_IP 一致)
if [[ -f "$ENV_FILE" ]]; then
set -a
# shellcheck source=/dev/null
source "$ENV_FILE"
set +a
fi
DEPLOY_TEST_IP="${DEPLOY_TEST_IP:-127.0.0.1}"
normalize_pc_proxy_env
init_script_log # ← 脚本执行日志
header "启动前端开发服务器"
# ── 前端服务配置 ──────────────────────────────────────────────────────────────
# name → (目录, 包管理器, 启动命令, 环境变量, 端口描述)
declare -A FE_DIR=(
[meetingh5]="meetingh5"
[h5]="h5"
)
declare -A FE_PM=(
[meetingh5]="npm"
[h5]="npm"
)
declare -A FE_CMD=(
[meetingh5]="npm run dev"
[h5]="npm run dev"
)
declare -A FE_ENV=(
[meetingh5]=""
[h5]=""
)
declare -A FE_PORT=(
[meetingh5]=":5188"
[h5]=":3003"
)
declare -A FE_PORT_NUM=(
[meetingh5]="5188"
[h5]="3003"
)
_check_fe_port_free() {
local name="$1"
local port="${FE_PORT_NUM[$name]}"
local pids
info "检查 ${BOLD}$name${NC} 端口 $port ..."
pids="$(lsof -tiTCP:"$port" -sTCP:LISTEN 2>/dev/null || true)"
if [[ -n "$pids" ]]; then
error "$name 启动失败: 端口 $port 已被占用"
echo "占用进程:"
lsof -nP -iTCP:"$port" -sTCP:LISTEN 2>/dev/null || true
echo ""
echo "请先停止占用进程,例如:"
echo " ./deploy-test/stop-frontend.sh $name"
echo " lsof -ti :$port | xargs -r kill"
return 1
fi
}
_wait_fe_port_listen() {
local name="$1"
local port="${FE_PORT_NUM[$name]}"
local i
for i in {1..10}; do
if lsof -tiTCP:"$port" -sTCP:LISTEN &>/dev/null; then
return 0
fi
sleep 1
done
error "$name 启动后未监听预期端口 $port"
return 1
}
_kill_tree() {
local pid="$1" signal="${2:-TERM}"
local children child
children=$(pgrep -P "$pid" 2>/dev/null || true)
for child in $children; do
_kill_tree "$child" "$signal"
done
kill "-$signal" "$pid" 2>/dev/null || true
}
# ── 启动单个前端服务 ──────────────────────────────────────────────────────────
_start_fe() {
local name="$1"
local dir="$ROOT_DIR/${FE_DIR[$name]}"
local pm="${FE_PM[$name]}"
local cmd="${FE_CMD[$name]}"
local env_prefix="${FE_ENV[$name]}"
local pidfile="$PID_DIR/fe-${name}.pid"
local logfile="$LOG_DIR/fe-${name}.log"
local port="${FE_PORT_NUM[$name]}"
_check_fe_port_free "$name" || return 1
# 已在运行
if [[ -f "$pidfile" ]] && kill -0 "$(cat "$pidfile")" 2>/dev/null; then
warn "$name 已在运行 (端口=$port, PID=$(cat "$pidfile")),跳过"
return 0
fi
# 目录检查
if [[ ! -d "$dir" ]]; then
warn "$name 目录不存在 (端口=$port, 目录=$dir),跳过"
return 0
fi
# 依赖检查
if [[ ! -d "$dir/node_modules" ]]; then
warn "$name node_modules 不存在 (端口=$port),请先执行: ./deploy-test/06-install-frontend.sh $name"
return 1
fi
# 包管理器检查
if ! command -v "$pm" &>/dev/null; then
error "$name 需要 $pm,未安装 (端口=$port)"
return 1
fi
info "启动 ${BOLD}$name${NC} (端口=$port) ..."
# 写日志分隔符
{
echo ""
echo "──── 启动 $(date '+%Y-%m-%d %H:%M:%S') ────"
} >> "$logfile"
# 后台启动(带环境变量前缀)
(
cd "$dir"
if [[ -n "$env_prefix" ]]; then
# shellcheck disable=SC2086
nohup env $env_prefix $cmd >> "$logfile" 2>&1 &
else
# shellcheck disable=SC2086
nohup $cmd >> "$logfile" 2>&1 &
fi
echo $! > "$pidfile"
)
sleep 2
if [[ -f "$pidfile" ]] && kill -0 "$(cat "$pidfile")" 2>/dev/null; then
if ! _wait_fe_port_listen "$name"; then
local started_pid
started_pid="$(cat "$pidfile")"
warn "$name 未监听预期端口 $port,清理本次启动进程 (PID=$started_pid)"
_kill_tree "$started_pid" TERM
sleep 1
if kill -0 "$started_pid" 2>/dev/null; then
_kill_tree "$started_pid" KILL
fi
rm -f "$pidfile"
return 1
fi
success "$name (端口=$port, PID=$(cat "$pidfile")) ${FE_PORT[$name]}$logfile"
else
error "$name 启动失败 (端口=$port),查看日志:"
tail -20 "$logfile" 2>/dev/null || true
return 1
fi
}
# ── 入口 ─────────────────────────────────────────────────────────────────────
TARGET="${1:-all}"
FE_PROJECTS=(meetingh5 h5)
STATIC_FRONTENDS=(pc cms build-cms build-down)
_all_valid() {
for p in "${FE_PROJECTS[@]}"; do
[[ "$p" == "$1" ]] && return 0
done
return 1
}
if [[ "$TARGET" == "all" ]]; then
step "启动全部前端开发服务器"
FAILED=()
for proj in "${FE_PROJECTS[@]}"; do
if ! bash "$SCRIPT_PATH" "$proj"; then
FAILED+=("$proj")
fi
done
echo ""
echo -e "${BOLD}前端服务汇总:${NC}"
for proj in "${FE_PROJECTS[@]}"; do
local_pidfile="$PID_DIR/fe-${proj}.pid"
if [[ -f "$local_pidfile" ]] && kill -0 "$(cat "$local_pidfile")" 2>/dev/null; then
printf " ${GREEN}${NC} %-14s PID=%-7s %s\n" "$proj" "$(cat "$local_pidfile")" "${FE_PORT[$proj]}"
else
printf " ${RED}${NC} %-14s 未运行 %s\n" "$proj" "${FE_PORT[$proj]}"
fi
done
echo ""
echo -e "${BOLD}访问地址:${NC}"
echo " H5: http://${DEPLOY_TEST_IP}:3003"
echo " Build Download: http://${DEPLOY_TEST_IP}:8003"
echo ""
echo -e "${BOLD}MeetingH5 访问地址(后端 URL 由 .env.local 默认设置,也可通过 URL 参数覆盖):${NC}"
echo " 默认: http://${DEPLOY_TEST_IP}:5188"
echo " 显式指定后端: http://${DEPLOY_TEST_IP}:5188?ws=ws://${DEPLOY_TEST_IP}:8000&liveApi=http://${DEPLOY_TEST_IP}:8888"
echo " 说明: ws → meetingmsg 弹幕 WebSocket (:8000)"
echo " liveApi → livestream 直播间 API (:8888)"
if [[ ${#FAILED[@]} -gt 0 ]]; then
echo ""
warn "以下项目启动失败: ${FAILED[*]}"
echo " 可能原因: node_modules 未安装,执行: ./deploy-test/06-install-frontend.sh"
fi
else
for static_fe in "${STATIC_FRONTENDS[@]}"; do
if [[ "$TARGET" == "$static_fe" ]]; then
error "$TARGET 已改为静态构建,不再通过 07-start-frontend.sh 启动"
echo "请执行: ./deploy-test/08-build-static-frontend.sh $TARGET"
echo "然后执行: sudo ./deploy-test/00-init-tools.sh nginx"
exit 1
fi
done
if ! _all_valid "$TARGET"; then
error "未知项目: $TARGET"
echo "开发态前端可用: ${FE_PROJECTS[*]}"
echo "静态前端请用: ./deploy-test/08-build-static-frontend.sh [pc|cms|build-cms|build-down]"
exit 1
fi
step "启动前端项目: $TARGET"
_start_fe "$TARGET"
fi