Files
shz-admin/local.sh

232 lines
5.3 KiB
Bash
Raw Normal View History

#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
RUNTIME_DIR="${RUNTIME_DIR:-${ROOT_DIR}/.local}"
LOG_DIR="${RUNTIME_DIR}/logs"
LOG_FILE="${LOG_FILE:-${LOG_DIR}/frontend.log}"
PID_FILE="${PID_FILE:-${RUNTIME_DIR}/frontend.pid}"
BACKEND_URL="${LOCAL_BACKEND_URL:-http://127.0.0.1:9091}"
FRONTEND_PORT="${PORT:-8000}"
NPM_CMD="${NPM_CMD:-npm}"
MAX_CMD="${ROOT_DIR}/node_modules/.bin/max"
info() {
printf '\033[1;32m%s\033[0m\n' "$*"
}
error() {
printf '\033[1;31m%s\033[0m\n' "$*" >&2
}
usage() {
cat <<'EOF'
用法:./local.sh <命令> [参数]
命令:
install 使用 package-lock.json 安装依赖
start [--skip-install] 检查本地后端并在后台启动前端
stop 停止本脚本启动的前端进程
restart [--skip-install] 重启前端
status 查看前端和本地后端状态
logs [行数] 查看并持续跟踪日志,默认显示最后 200
help 显示帮助
可选环境变量:
LOCAL_BACKEND_URL 本地后端地址,默认 http://127.0.0.1:9091
PORT 前端端口,默认 8000
NPM_CMD npm 命令,默认 npm
EOF
}
prepare_runtime() {
mkdir -p "${LOG_DIR}"
}
read_pid() {
if [[ -f "${PID_FILE}" ]]; then
tr -d '[:space:]' < "${PID_FILE}"
fi
}
is_running() {
local pid
pid="$(read_pid)"
[[ -n "${pid}" ]] && kill -0 "${pid}" 2>/dev/null
}
install_dependencies() {
command -v "${NPM_CMD}" >/dev/null 2>&1 || {
error "未找到 npm 命令:${NPM_CMD}"
exit 1
}
info "正在根据 package-lock.json 安装依赖..."
(
cd "${ROOT_DIR}"
"${NPM_CMD}" ci
)
}
check_backend() {
local status
command -v curl >/dev/null 2>&1 || {
error "未找到 curl无法检查本地后端"
exit 1
}
status="$(curl -s -o /dev/null --max-time 3 -w '%{http_code}' "${BACKEND_URL}/" || true)"
if [[ -z "${status}" || "${status}" == "000" ]]; then
error "本地后端不可访问:${BACKEND_URL}"
error "请先在 shz-backend 中执行:./local.sh start"
exit 1
fi
info "本地后端已连接:${BACKEND_URL}HTTP ${status}"
}
start_frontend() {
local skip_install="${1:-}"
prepare_runtime
if is_running; then
info "前端已在运行PID$(read_pid)"
return 0
fi
rm -f "${PID_FILE}"
check_backend
if [[ ! -x "${MAX_CMD}" ]]; then
if [[ "${skip_install}" == "--skip-install" ]]; then
error "依赖尚未安装,不能跳过安装:${MAX_CMD} 不存在"
exit 1
fi
install_dependencies
elif [[ -n "${skip_install}" && "${skip_install}" != "--skip-install" ]]; then
error "未知参数:${skip_install}"
exit 2
fi
export REACT_APP_ENV=dev
export MOCK=none
export UMI_ENV=dev
export LOCAL_BACKEND_URL="${BACKEND_URL}"
export PORT="${FRONTEND_PORT}"
info "正在启动前端http://localhost:${FRONTEND_PORT}"
info "后端代理目标:${BACKEND_URL}"
(
cd "${ROOT_DIR}"
nohup "${MAX_CMD}" dev >> "${LOG_FILE}" 2>&1 &
printf '%s\n' "$!" > "${PID_FILE}"
)
local frontend_status="000"
for _ in {1..60}; do
if ! is_running; then
break
fi
frontend_status="$(curl -s -o /dev/null --max-time 1 -w '%{http_code}' \
"http://127.0.0.1:${FRONTEND_PORT}/" || true)"
if [[ -n "${frontend_status}" && "${frontend_status}" != "000" ]]; then
info "前端已启动PID$(read_pid)HTTP ${frontend_status}"
info "日志命令:./local.sh logs"
return 0
fi
sleep 1
done
rm -f "${PID_FILE}"
error "前端未能在 60 秒内启动,最近日志如下:"
tail -n 80 "${LOG_FILE}" >&2 || true
exit 1
}
stop_frontend() {
local pid
pid="$(read_pid)"
if ! is_running; then
rm -f "${PID_FILE}"
info "前端未运行"
return 0
fi
info "正在停止前端PID${pid}"
kill "${pid}"
for _ in {1..15}; do
if ! kill -0 "${pid}" 2>/dev/null; then
rm -f "${PID_FILE}"
info "前端已停止"
return 0
fi
sleep 1
done
error "前端未在 15 秒内停止,请检查 PID${pid}"
exit 1
}
show_status() {
local backend_status
if is_running; then
info "前端正在运行PID$(read_pid)地址http://localhost:${FRONTEND_PORT}"
else
rm -f "${PID_FILE}"
info "前端未运行"
fi
backend_status="$(curl -s -o /dev/null --max-time 2 -w '%{http_code}' "${BACKEND_URL}/" || true)"
if [[ -n "${backend_status}" && "${backend_status}" != "000" ]]; then
info "本地后端可访问:${BACKEND_URL}HTTP ${backend_status}"
else
error "本地后端不可访问:${BACKEND_URL}"
fi
info "日志文件:${LOG_FILE}"
}
show_logs() {
local lines="${1:-200}"
if [[ ! "${lines}" =~ ^[0-9]+$ ]]; then
error "日志行数必须是非负整数:${lines}"
exit 2
fi
prepare_runtime
touch "${LOG_FILE}"
info "正在跟踪日志:${LOG_FILE}Ctrl+C 退出)"
tail -n "${lines}" -f "${LOG_FILE}"
}
command="${1:-help}"
case "${command}" in
install)
install_dependencies
;;
start)
start_frontend "${2:-}"
;;
stop)
stop_frontend
;;
restart)
stop_frontend
start_frontend "${2:-}"
;;
status)
show_status
;;
logs)
show_logs "${2:-200}"
;;
help|-h|--help)
usage
;;
*)
error "未知命令:${command}"
usage >&2
exit 2
;;
esac