Forráskód Böngészése

添加一键启动脚本 start.sh (start/stop/restart/status/logs)

admin 1 hete
szülő
commit
33f61c9f1d
1 módosított fájl, 249 hozzáadás és 0 törlés
  1. 249 0
      start.sh

+ 249 - 0
start.sh

@@ -0,0 +1,249 @@
+#!/bin/bash
+# KVM Manager 一键启动脚本
+# 用法: ./start.sh [start|stop|restart|status]
+set -e
+
+# ── 配置 ──────────────────────────────────────────────
+SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
+BACKEND_DIR="$SCRIPT_DIR/backend"
+FRONTEND_DIR="$SCRIPT_DIR/frontend"
+LOG_DIR="$SCRIPT_DIR/logs"
+PID_DIR="$SCRIPT_DIR/.pid"
+
+BACKEND_PORT=8004
+FRONTEND_PORT=8006
+BACKEND_CMD="$BACKEND_DIR/venv/bin/python -m uvicorn app.main:app --host 0.0.0.0 --port $BACKEND_PORT"
+FRONTEND_CMD="$BACKEND_DIR/venv/bin/python $FRONTEND_DIR/serve.py"
+
+# ── 颜色 ──────────────────────────────────────────────
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+CYAN='\033[0;36m'
+NC='\033[0m'
+
+# ── 工具函数 ──────────────────────────────────────────
+info()  { echo -e "${CYAN}[INFO]${NC} $1"; }
+ok()    { echo -e "${GREEN}[OK]${NC} $1"; }
+warn()  { echo -e "${YELLOW}[WARN]${NC} $1"; }
+fail()  { echo -e "${RED}[FAIL]${NC} $1"; }
+
+mkdir -p "$LOG_DIR" "$PID_DIR"
+
+# 检查端口是否被占用,返回 PID
+port_pid() {
+    lsof -ti:$1 2>/dev/null | head -1
+}
+
+# 等待端口可用
+wait_port() {
+    local port=$1 name=$2 max=10 count=0
+    while [ $count -lt $max ]; do
+        if port_pid $port >/dev/null 2>&1; then
+            return 0
+        fi
+        sleep 1
+        count=$((count + 1))
+    done
+    return 1
+}
+
+# ── 启动后端 ──────────────────────────────────────────
+start_backend() {
+    info "启动后端服务 (端口 $BACKEND_PORT)..."
+
+    # 检查是否已运行
+    local existing_pid=$(port_pid $BACKEND_PORT)
+    if [ -n "$existing_pid" ]; then
+        warn "后端已在运行 (PID: $existing_pid)"
+        return 0
+    fi
+
+    # 检查 venv
+    if [ ! -d "$BACKEND_DIR/venv" ]; then
+        fail "未找到 Python 虚拟环境,请先运行: cd backend && python3 -m venv venv && source venv/bin/activate && pip install -r requirements.txt"
+        return 1
+    fi
+
+    # 检查 libvirtd
+    if ! systemctl is-active --quiet libvirtd 2>/dev/null; then
+        warn "libvirtd 未运行,尝试启动..."
+        systemctl start libvirtd 2>/dev/null || warn "libvirtd 启动失败,后端可能无法连接虚拟机"
+    fi
+
+    cd "$BACKEND_DIR"
+    nohup $BACKEND_CMD > "$LOG_DIR/backend.log" 2>&1 &
+    local pid=$!
+    echo $pid > "$PID_DIR/backend.pid"
+
+    sleep 2
+    if port_pid $BACKEND_PORT >/dev/null 2>&1; then
+        ok "后端服务已启动 (PID: $pid, 端口: $BACKEND_PORT)"
+        ok "日志: $LOG_DIR/backend.log"
+    else
+        fail "后端服务启动失败,查看日志:"
+        tail -20 "$LOG_DIR/backend.log"
+        return 1
+    fi
+}
+
+# ── 启动前端 ──────────────────────────────────────────
+start_frontend() {
+    info "启动前端服务 (端口 $FRONTEND_PORT)..."
+
+    local existing_pid=$(port_pid $FRONTEND_PORT)
+    if [ -n "$existing_pid" ]; then
+        warn "前端已在运行 (PID: $existing_pid)"
+        return 0
+    fi
+
+    # 检查 dist
+    if [ ! -d "$FRONTEND_DIR/dist" ]; then
+        warn "未找到前端构建产物,正在构建..."
+        cd "$FRONTEND_DIR"
+        npm install --silent && npm run build
+        if [ ! -d "$FRONTEND_DIR/dist" ]; then
+            fail "前端构建失败"
+            return 1
+        fi
+        ok "前端构建完成"
+    fi
+
+    cd "$FRONTEND_DIR"
+    nohup $FRONTEND_CMD > "$LOG_DIR/frontend.log" 2>&1 &
+    local pid=$!
+    echo $pid > "$PID_DIR/frontend.pid"
+
+    sleep 2
+    if port_pid $FRONTEND_PORT >/dev/null 2>&1; then
+        ok "前端服务已启动 (PID: $pid, 端口: $FRONTEND_PORT)"
+        ok "日志: $LOG_DIR/frontend.log"
+    else
+        fail "前端服务启动失败,查看日志:"
+        tail -20 "$LOG_DIR/frontend.log"
+        return 1
+    fi
+}
+
+# ── 停止服务 ──────────────────────────────────────────
+stop_service() {
+    local name=$1 port=$2 pidfile=$PID_DIR/$3.pid
+    info "停止 $name (端口 $port)..."
+
+    # 先尝试 PID 文件
+    if [ -f "$pidfile" ]; then
+        local pid=$(cat "$pidfile")
+        if ps -p "$pid" >/dev/null 2>&1; then
+            kill "$pid" 2>/dev/null && ok "$name 已停止 (PID: $pid)" || warn "$name 停止失败"
+        fi
+        rm -f "$pidfile"
+    fi
+
+    # 再检查端口残留
+    local residual=$(port_pid $port)
+    if [ -n "$residual" ]; then
+        kill "$residual" 2>/dev/null && ok "$name 残留进程已清理 (PID: $residual)" || true
+    fi
+}
+
+stop_all() {
+    info "停止所有服务..."
+    stop_service "后端" $BACKEND_PORT "backend"
+    stop_service "前端" $FRONTEND_PORT "frontend"
+    ok "所有服务已停止"
+}
+
+# ── 状态 ──────────────────────────────────────────────
+show_status() {
+    echo ""
+    echo -e "${CYAN}========================================${NC}"
+    echo -e "${CYAN}    KVM Manager 服务状态${NC}"
+    echo -e "${CYAN}========================================${NC}"
+
+    # 后端
+    local bpid=$(port_pid $BACKEND_PORT)
+    if [ -n "$bpid" ]; then
+        echo -e "  后端:  ${GREEN}● 运行中${NC}  PID: $bpid  端口: $BACKEND_PORT"
+    else
+        echo -e "  后端:  ${RED}○ 未运行${NC}"
+    fi
+
+    # 前端
+    local fpid=$(port_pid $FRONTEND_PORT)
+    if [ -n "$fpid" ]; then
+        echo -e "  前端:  ${GREEN}● 运行中${NC}  PID: $fpid  端口: $FRONTEND_PORT"
+    else
+        echo -e "  前端:  ${RED}○ 未运行${NC}"
+    fi
+
+    echo ""
+    echo -e "  访问地址: ${YELLOW}http://localhost:$FRONTEND_PORT${NC}"
+    echo -e "  API文档:  ${YELLOW}http://localhost:$BACKEND_PORT/docs${NC}"
+    echo -e "  日志目录: ${YELLOW}$LOG_DIR${NC}"
+    echo ""
+}
+
+# ── 查看日志 ──────────────────────────────────────────
+show_logs() {
+    local target=${1:-all}
+    case $target in
+        backend|b)  tail -f "$LOG_DIR/backend.log" 2>/dev/null || fail "后端日志不存在" ;;
+        frontend|f) tail -f "$LOG_DIR/frontend.log" 2>/dev/null || fail "前端日志不存在" ;;
+        *)          tail -f "$LOG_DIR/backend.log" "$LOG_DIR/frontend.log" 2>/dev/null || fail "日志不存在" ;;
+    esac
+}
+
+# ── 主入口 ────────────────────────────────────────────
+usage() {
+    echo ""
+    echo -e "${CYAN}KVM Manager 一键启动脚本${NC}"
+    echo ""
+    echo "用法: $0 <命令>"
+    echo ""
+    echo "命令:"
+    echo "  start    启动所有服务 (默认)"
+    echo "  stop     停止所有服务"
+    echo "  restart  重启所有服务"
+    echo "  status   查看服务状态"
+    echo "  logs     查看日志 (logs backend/frontend)"
+    echo ""
+    echo "示例:"
+    echo "  $0              # 启动所有"
+    echo "  $0 start        # 启动所有"
+    echo "  $0 stop         # 停止所有"
+    echo "  $0 restart      # 重启所有"
+    echo "  $0 status       # 查看状态"
+    echo "  $0 logs backend # 查看后端日志"
+    echo ""
+}
+
+case "${1:-start}" in
+    start)
+        start_backend
+        start_frontend
+        show_status
+        ;;
+    stop)
+        stop_all
+        ;;
+    restart)
+        stop_all
+        sleep 1
+        start_backend
+        start_frontend
+        show_status
+        ;;
+    status)
+        show_status
+        ;;
+    logs)
+        show_logs "${2:-all}"
+        ;;
+    -h|--help|help)
+        usage
+        ;;
+    *)
+        usage
+        exit 1
+        ;;
+esac