material_manage_system/dev-verify.sh
copper-xw 6a16edfa24 fix: 修正试用脚本就绪探测并支持端口可配置
MySQL 就绪探测改为走 TCP(127.0.0.1:3306),避免初始化阶段只监听 socket
的临时服务器让探测提前通过,导致后端连入时遇到 unexpected EOF。
后端监听端口改为读取 APP_PORT(默认 8082),与脚本探测的空闲端口一致,
并在启动时和最终提示中打印完整访问地址;npm 默认使用 npmmirror 镜像,
同时将根目录编译产物 /server 加入忽略。
2026-09-30 17:39:03 +08:00

152 lines
5.1 KiB
Bash
Executable File
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
# 一次性试用脚本:本机编译前后端,Docker 仅跑一个一次性 MySQL,数据全部隔离。
#
# 特性:
# - 前端本机 vite build -> frontend/dist(由后端直接托管)
# - 后端本机 go build -> .dev-run/ 下的二进制,本机直接运行
# - MySQL 用独立容器 wmms-dev-mysql + 匿名卷,只绑本机,不影响其他环境
# - 自动探测空闲端口:后端默认从 8080 起,MySQL 从 13306 起
# - 每次都是全新数据库(执行 scripts/init.sql)
# - 按 Ctrl+C 停止并删除二进制目录与 MySQL 容器/数据卷
#
# 可选环境变量:
# APP_PORT 期望的网页端口;被占用时自动顺延(默认 8080)
# DB_PORT 期望映射到本机的 MySQL 端口;被占用时顺延(默认 13306)
# KEEP_DATA=1 退出时保留 .dev-run/ 和 MySQL 容器(默认全部删除)
# NPM_REGISTRY 重装依赖时使用的 npm 镜像源(默认 https://registry.npmmirror.com)
set -euo pipefail
cd "$(dirname "$0")"
RUNDIR="$PWD/.dev-run"
DB_CONTAINER="wmms-dev-mysql"
DB_PASSWORD="wmms1234"
DB_NAME="wmms"
# 默认走国内镜像,避免官方源 ECONNRESET;可用 NPM_REGISTRY 覆盖。
NPM_REGISTRY="${NPM_REGISTRY:-https://registry.npmmirror.com}"
find_free_port() {
local start="$1" p="$1"
for ((i = 0; i < 100; i++)); do
if ! ss -ltn 2>/dev/null | awk '{print $4}' | grep -Eq "[:.]$p$"; then
echo "$p"
return
fi
p=$((p + 1))
done
echo "$start"
}
cleaned=0
PID=""
cleanup() {
[ "$cleaned" = "1" ] && return
cleaned=1
echo
echo "==> 停止服务"
[ -n "$PID" ] && kill "$PID" 2>/dev/null || true
if [ "${KEEP_DATA:-0}" = "1" ]; then
echo "==> KEEP_DATA=1,保留 $RUNDIR 与容器 $DB_CONTAINER"
else
docker rm -f "$DB_CONTAINER" >/dev/null 2>&1 || true
rm -rf "$RUNDIR"
echo "==> 已删除 MySQL 容器/数据卷与 $RUNDIR"
fi
}
trap cleanup EXIT INT TERM
APP_PORT="$(find_free_port "${APP_PORT:-8080}")"
DB_PORT="$(find_free_port "${DB_PORT:-13306}")"
echo "==> 1/4 构建前端(vite build)"
(
cd frontend
# 随仓库带来的 node_modules 可能是在 Windows 上安装的:缺 Linux 平台的
# rollup 原生包,且 .bin 丢失可执行位。这种情况下用 npm ci 按 lock 重装。
need_install=0
if [ ! -d node_modules ]; then
need_install=1
elif [ ! -d node_modules/@rollup/rollup-linux-x64-gnu ] && [ ! -d node_modules/@rollup/rollup-linux-x64-musl ]; then
echo " 检测到 node_modules 非 Linux 平台安装,重新安装依赖..."
need_install=1
fi
if [ "$need_install" = "1" ]; then
npm ci --registry="$NPM_REGISTRY"
else
chmod +x node_modules/.bin/* 2>/dev/null || true
fi
npm run build
)
echo "==> 2/4 构建后端(go build)"
mkdir -p "$RUNDIR"
BIN="$RUNDIR/server"
go build -o "$BIN" ./cmd/server
# 若已有同名残留容器(上次异常退出),先清掉。
docker rm -f "$DB_CONTAINER" >/dev/null 2>&1 || true
echo "==> 3/4 启动一次性 MySQL(容器 $DB_CONTAINER,本机端口 $DB_PORT)"
docker run -d --name "$DB_CONTAINER" \
-e MYSQL_ROOT_PASSWORD="$DB_PASSWORD" \
-e MYSQL_DATABASE="$DB_NAME" \
-p "127.0.0.1:$DB_PORT:3306" \
-v "$PWD/scripts/init.sql:/docker-entrypoint-initdb.d/001-init.sql:ro" \
mysql:8.0 \
--default-authentication-plugin=mysql_native_password \
--character-set-server=utf8mb4 \
--collation-server=utf8mb4_unicode_ci >/dev/null
echo " 等待 MySQL 就绪..."
for ((i = 0; i < 90; i++)); do
# 必须走 TCP(127.0.0.1:3306),不能用 localhost 的 socket:初始化阶段的
# 临时服务器只监听 socket,socket ping 会提前成功,但 3306 尚未就绪,
# 后端连入时正逢重启,报 unexpected EOF / bad connection。
if docker exec "$DB_CONTAINER" mysqladmin ping -h 127.0.0.1 -P 3306 -uroot -p"$DB_PASSWORD" --silent >/dev/null 2>&1; then
break
fi
if ! docker ps --format '{{.Names}}' | grep -qx "$DB_CONTAINER"; then
echo "MySQL 容器意外退出,日志:"
docker logs "$DB_CONTAINER" 2>&1 | tail -40 || true
exit 1
fi
sleep 1
done
echo "==> 4/4 启动后端(端口 $APP_PORT)"
echo " 访问地址: http://localhost:$APP_PORT"
DSN="root:$DB_PASSWORD@tcp(127.0.0.1:$DB_PORT)/$DB_NAME?charset=utf8mb4&parseTime=true"
APP_PORT="$APP_PORT" DB_DSN="$DSN" "$BIN" &
PID=$!
READY=0
for ((i = 0; i < 60; i++)); do
if curl -fsS "http://localhost:$APP_PORT/api/health" >/dev/null 2>&1; then
READY=1
break
fi
if ! kill -0 "$PID" 2>/dev/null; then
echo "后端进程意外退出,请查看上方日志"
exit 1
fi
sleep 0.5
done
if [ "$READY" != "1" ]; then
echo "警告:未检测到服务就绪,后端日志:"
wait "$PID" || true
exit 1
fi
echo
echo "============================================================"
echo " 试用环境已启动(数据一次性,关闭即清除,不影响其他环境)"
echo " 访问地址: http://localhost:$APP_PORT"
echo " 账号:admin / admin123 user / user123"
echo " 按 Ctrl+C 停止并删除 MySQL 容器与临时文件"
echo "============================================================"
echo
wait "$PID"