#!/bin/sh # 沃林学生管理系统 —— 容器启动脚本 # 顺序:等 MySQL → (可选)建表建账号 → (可选)灌演示数据 → 起 uvicorn set -e echo "==========================================================" echo " 沃林学生管理系统 · 容器启动" echo "==========================================================" echo " 工作目录 : $(pwd)" echo " 数据库 : ${DB_DRIVER}://${DB_USER}@${DB_HOST}:${DB_PORT}/${DB_NAME}" echo " 监听端口 : 0.0.0.0:${APP_PORT:-8000}" echo "----------------------------------------------------------" wait_for_db() { if [ "${INIT_DB}" != "true" ]; then echo "[wait] INIT_DB=false,跳过数据库等待" return 0 fi echo "[wait] 等待 MySQL (${DB_HOST}:${DB_PORT}) 就绪,最长 ${DB_WAIT_TIMEOUT:-120}s ..." i=0 while [ "$i" -lt "${DB_WAIT_TIMEOUT:-120}" ]; do if python -c " import sys from sqlalchemy import create_engine, text from app.core.config import settings try: e = create_engine(settings.server_url_without_db, future=True) with e.connect() as c: c.execute(text('SELECT 1')) e.dispose() except Exception: sys.exit(1) sys.exit(0) " 2>/dev/null; then echo "[wait] MySQL 已就绪(用时 ${i}s)" return 0 fi i=$((i + 2)) sleep 2 done echo "[wait] 错误:等待 ${DB_WAIT_TIMEOUT:-120}s 后 MySQL 仍不可用" >&2 return 1 } wait_for_db if [ "${INIT_DB}" = "true" ]; then echo "[init] 建库 / 建表 / 建初始账号 ..." python -m app.scripts.init_db else echo "[init] INIT_DB=false,跳过建表" fi if [ "${SEED_DATA}" = "true" ]; then echo "[seed] 灌入演示数据(已有数据会自动跳过)..." python -m app.scripts.seed_data || echo "[seed] 灌数据失败,继续启动(不影响服务)" else echo "[seed] SEED_DATA=false,跳过演示数据" fi echo "----------------------------------------------------------" echo " 首页 http://<宿主机>:<映射端口>/" echo " 接口文档 http://<宿主机>:<映射端口>/docs" echo " 管理员 admin / admin123" echo " 只读账号 viewer / viewer123" echo "==========================================================" echo "[run] uvicorn 启动中 ..." exec uvicorn app.main:app --host 0.0.0.0 --port "${APP_PORT:-8000}"