|
@@ -0,0 +1,239 @@
|
|
|
|
|
+#!/bin/bash
|
|
|
|
|
+
|
|
|
|
|
+# ============================================================
|
|
|
|
|
+# 智能柜项目一键部署脚本 (4核8G 服务器优化版)
|
|
|
|
|
+# 用法: ./deploy.sh [admin|miniapp|all] [--skip-frontend] [--no-stop]
|
|
|
|
|
+# --no-stop 构建前不停止服务 (零停机,JVM 已限制内存)
|
|
|
|
|
+# 调试: bash -x ./deploy.sh
|
|
|
|
|
+# ============================================================
|
|
|
|
|
+
|
|
|
|
|
+APP_DIR="/data/app"
|
|
|
|
|
+CODE_DIR="/data/code/haha"
|
|
|
|
|
+BACKUP_DIR="/data/backup"
|
|
|
|
|
+LOG_DIR="/data/logs"
|
|
|
|
|
+HISTORY_FILE="/data/history"
|
|
|
|
|
+
|
|
|
|
|
+RED='\033[0;31m'
|
|
|
|
|
+GREEN='\033[0;32m'
|
|
|
|
|
+YELLOW='\033[1;33m'
|
|
|
|
|
+NC='\033[0m'
|
|
|
|
|
+
|
|
|
|
|
+log() { echo -e "[$(date '+%H:%M:%S')] $1"; }
|
|
|
|
|
+info() { log "${GREEN}INFO${NC} $1"; }
|
|
|
|
|
+warn() { log "${YELLOW}WARN${NC} $1"; }
|
|
|
|
|
+error() { log "${RED}ERROR${NC} $1"; }
|
|
|
|
|
+
|
|
|
|
|
+mkdir -p "$LOG_DIR" "$BACKUP_DIR"
|
|
|
|
|
+
|
|
|
|
|
+# ============================================================
|
|
|
|
|
+# 资源限制配置 (4核8G 服务器)
|
|
|
|
|
+# ============================================================
|
|
|
|
|
+
|
|
|
|
|
+# ---- 构建阶段 ----
|
|
|
|
|
+NODE_MAX_MEM="${NODE_MAX_MEM:-2048}" # Node 最大 old-space MB
|
|
|
|
|
+MAVEN_XMX="${MAVEN_XMX:-1024}" # Maven JVM 最大堆 MB
|
|
|
|
|
+MAVEN_XMS="${MAVEN_XMS:-256}" # Maven JVM 初始堆 MB
|
|
|
|
|
+MAVEN_THREADS="${MAVEN_THREADS:-2}" # Maven 编译线程数
|
|
|
|
|
+
|
|
|
|
|
+# ---- 运行时 JVM (admin 模块) ----
|
|
|
|
|
+ADMIN_XMX="${ADMIN_XMX:-1536}" # 最大堆 MB
|
|
|
|
|
+ADMIN_XMS="${ADMIN_XMS:-256}" # 初始堆 MB
|
|
|
|
|
+ADMIN_META="${ADMIN_META:-256}" # 元空间上限 MB
|
|
|
|
|
+ADMIN_CODE_CACHE="${ADMIN_CODE_CACHE:-128}" # JIT 代码缓存 MB
|
|
|
|
|
+ADMIN_XSS="${ADMIN_XSS:-256}" # 线程栈 KB
|
|
|
|
|
+
|
|
|
|
|
+# ---- 运行时 JVM (miniapp 模块) ----
|
|
|
|
|
+MINIAPP_XMX="${MINIAPP_XMX:-1024}"
|
|
|
|
|
+MINIAPP_XMS="${MINIAPP_XMS:-256}"
|
|
|
|
|
+MINIAPP_META="${MINIAPP_META:-256}"
|
|
|
|
|
+MINIAPP_CODE_CACHE="${MINIAPP_CODE_CACHE:-128}"
|
|
|
|
|
+MINIAPP_XSS="${MINIAPP_XSS:-256}"
|
|
|
|
|
+
|
|
|
|
|
+# 低优先级包装器
|
|
|
|
|
+low_prio() {
|
|
|
|
|
+ nice -n 19 ionice -c 2 -n 7 "$@"
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+# ---- 参数解析 ----
|
|
|
|
|
+TARGET="${1:-all}"
|
|
|
|
|
+SKIP_FRONTEND=false
|
|
|
|
|
+NO_STOP=false
|
|
|
|
|
+for arg in "$@"; do
|
|
|
|
|
+ [ "$arg" = "--skip-frontend" ] && SKIP_FRONTEND=true
|
|
|
|
|
+ [ "$arg" = "--no-stop" ] && NO_STOP=true
|
|
|
|
|
+done
|
|
|
|
|
+
|
|
|
|
|
+info "开始部署 (目标=$TARGET, 零停机=$NO_STOP)"
|
|
|
|
|
+info "Node:${NODE_MAX_MEM}M | Maven:${MAVEN_XMX}M | Admin-JVM:${ADMIN_XMX}M | Miniapp-JVM:${MINIAPP_XMX}M"
|
|
|
|
|
+
|
|
|
|
|
+# ---- 拉取代码 ----
|
|
|
|
|
+info "拉取最新代码..."
|
|
|
|
|
+cd "$CODE_DIR" || { error "无法进入 $CODE_DIR"; exit 1; }
|
|
|
|
|
+low_prio git pull origin master || { error "git pull 失败"; exit 1; }
|
|
|
|
|
+
|
|
|
|
|
+# ============================================================
|
|
|
|
|
+# 阶段 1: 停止服务 (释放内存给构建)
|
|
|
|
|
+# ============================================================
|
|
|
|
|
+stop_service() {
|
|
|
|
|
+ local module=$1
|
|
|
|
|
+ local pid=$(ps -ef | grep java | grep "$module" | grep -v grep | awk '{print $2}')
|
|
|
|
|
+
|
|
|
|
|
+ if [ -z "$pid" ]; then
|
|
|
|
|
+ info "$module 未在运行"
|
|
|
|
|
+ return 0
|
|
|
|
|
+ fi
|
|
|
|
|
+
|
|
|
|
|
+ for p in $pid; do
|
|
|
|
|
+ info "终止 $module (pid=$p)..."
|
|
|
|
|
+ kill "$p" 2>/dev/null
|
|
|
|
|
+
|
|
|
|
|
+ for i in $(seq 1 10); do
|
|
|
|
|
+ if ! kill -0 "$p" 2>/dev/null; then
|
|
|
|
|
+ info "进程 $p 已退出"
|
|
|
|
|
+ break
|
|
|
|
|
+ fi
|
|
|
|
|
+ sleep 1
|
|
|
|
|
+ done
|
|
|
|
|
+
|
|
|
|
|
+ if kill -0 "$p" 2>/dev/null; then
|
|
|
|
|
+ warn "强制终止 $p"
|
|
|
|
|
+ kill -9 "$p" 2>/dev/null
|
|
|
|
|
+ sleep 1
|
|
|
|
|
+ fi
|
|
|
|
|
+ done
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+if [ "$NO_STOP" = false ]; then
|
|
|
|
|
+ case "$TARGET" in
|
|
|
|
|
+ admin) stop_service "haha-admin" ;;
|
|
|
|
|
+ miniapp) stop_service "haha-miniapp" ;;
|
|
|
|
|
+ all) stop_service "haha-admin"
|
|
|
|
|
+ stop_service "haha-miniapp" ;;
|
|
|
|
|
+ esac
|
|
|
|
|
+ sleep 3
|
|
|
|
|
+fi
|
|
|
|
|
+
|
|
|
|
|
+# ============================================================
|
|
|
|
|
+# 阶段 2: 构建
|
|
|
|
|
+# ============================================================
|
|
|
|
|
+
|
|
|
|
|
+if [ "$SKIP_FRONTEND" = false ] && [ "$TARGET" != "miniapp" ]; then
|
|
|
|
|
+ info "构建前端 admin-web ..."
|
|
|
|
|
+ (
|
|
|
|
|
+ cd "$CODE_DIR/haha-admin-web" || exit 1
|
|
|
|
|
+ export NODE_OPTIONS="--max-old-space-size=$NODE_MAX_MEM"
|
|
|
|
|
+ low_prio npm run build
|
|
|
|
|
+ ) || { error "admin-web 构建失败"; exit 1; }
|
|
|
|
|
+ info "admin-web 构建完成"
|
|
|
|
|
+ sleep 2
|
|
|
|
|
+fi
|
|
|
|
|
+
|
|
|
|
|
+export MAVEN_OPTS="-Xmx${MAVEN_XMX}m -Xms${MAVEN_XMS}m -XX:+UseSerialGC"
|
|
|
|
|
+
|
|
|
|
|
+if [ "$TARGET" = "miniapp" ]; then
|
|
|
|
|
+ info "Maven 打包 (仅 miniapp)..."
|
|
|
|
|
+ (
|
|
|
|
|
+ cd "$CODE_DIR"
|
|
|
|
|
+ low_prio mvn clean package -DskipTests -pl haha-miniapp -am \
|
|
|
|
|
+ -T "${MAVEN_THREADS}" -Dmaven.test.skip=true
|
|
|
|
|
+ ) || { error "Maven 打包失败"; exit 1; }
|
|
|
|
|
+else
|
|
|
|
|
+ info "Maven 打包 (全量, 线程=${MAVEN_THREADS})..."
|
|
|
|
|
+ (
|
|
|
|
|
+ cd "$CODE_DIR"
|
|
|
|
|
+ low_prio mvn clean package -DskipTests \
|
|
|
|
|
+ -T "${MAVEN_THREADS}" \
|
|
|
|
|
+ -Dmaven.test.skip=true \
|
|
|
|
|
+ -Dmaven.compiler.fork=false
|
|
|
|
|
+ ) || { error "Maven 打包失败"; exit 1; }
|
|
|
|
|
+fi
|
|
|
|
|
+
|
|
|
|
|
+sleep 2
|
|
|
|
|
+
|
|
|
|
|
+# ============================================================
|
|
|
|
|
+# 阶段 3: 备份 & 部署 & 启动
|
|
|
|
|
+# ============================================================
|
|
|
|
|
+
|
|
|
|
|
+backup_and_copy() {
|
|
|
|
|
+ local module=$1
|
|
|
|
|
+ local jar_src="$CODE_DIR/$module/target/${module}-0.0.1-SNAPSHOT.jar"
|
|
|
|
|
+ local jar_dst="$APP_DIR/${module}-0.0.1-SNAPSHOT.jar"
|
|
|
|
|
+
|
|
|
|
|
+ if [ ! -f "$jar_src" ]; then
|
|
|
|
|
+ error "未找到 jar 文件: $jar_src"
|
|
|
|
|
+ exit 1
|
|
|
|
|
+ fi
|
|
|
|
|
+
|
|
|
|
|
+ if [ -f "$jar_dst" ]; then
|
|
|
|
|
+ cp "$jar_dst" "$BACKUP_DIR/${module}-0.0.1-SNAPSHOT.jar.$(date +%Y%m%d_%H%M%S)"
|
|
|
|
|
+ info "已备份 $module (保留最近 5 个)"
|
|
|
|
|
+ ls -t "$BACKUP_DIR/${module}"-*.jar 2>/dev/null | tail -n +6 | xargs -r rm -f
|
|
|
|
|
+ fi
|
|
|
|
|
+ cp "$jar_src" "$jar_dst"
|
|
|
|
|
+ info "$module jar 已复制到 $APP_DIR"
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+# 构建模块专用的 JVM 参数
|
|
|
|
|
+build_jvm_opts() {
|
|
|
|
|
+ local module=$1
|
|
|
|
|
+ if [ "$module" = "haha-admin" ]; then
|
|
|
|
|
+ echo "-Xmx${ADMIN_XMX}m -Xms${ADMIN_XMS}m -Xss${ADMIN_XSS}k \
|
|
|
|
|
+-XX:MaxMetaspaceSize=${ADMIN_META}m -XX:ReservedCodeCacheSize=${ADMIN_CODE_CACHE}m \
|
|
|
|
|
+-XX:+UseG1GC -XX:MaxGCPauseMillis=200"
|
|
|
|
|
+ else
|
|
|
|
|
+ echo "-Xmx${MINIAPP_XMX}m -Xms${MINIAPP_XMS}m -Xss${MINIAPP_XSS}k \
|
|
|
|
|
+-XX:MaxMetaspaceSize=${MINIAPP_META}m -XX:ReservedCodeCacheSize=${MINIAPP_CODE_CACHE}m \
|
|
|
|
|
+-XX:+UseG1GC -XX:MaxGCPauseMillis=200"
|
|
|
|
|
+ fi
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+start_service() {
|
|
|
|
|
+ local module=$1
|
|
|
|
|
+ local jar_file="${module}-0.0.1-SNAPSHOT.jar"
|
|
|
|
|
+ local start_log="$LOG_DIR/${module}.log"
|
|
|
|
|
+ local jvm_opts=$(build_jvm_opts "$module")
|
|
|
|
|
+
|
|
|
|
|
+ info "启动 $module (JVM: $(echo $jvm_opts | tr -s ' '))..."
|
|
|
|
|
+
|
|
|
|
|
+ cd "$APP_DIR"
|
|
|
|
|
+ nohup java $jvm_opts -jar -Dspring.profiles.active=prod "$jar_file" > "$start_log" 2>&1 &
|
|
|
|
|
+
|
|
|
|
|
+ sleep 5
|
|
|
|
|
+ local new_pid=$(ps -ef | grep java | grep "$module" | grep -v grep | awk '{print $2}')
|
|
|
|
|
+
|
|
|
|
|
+ if [ -n "$new_pid" ]; then
|
|
|
|
|
+ info "$module 启动成功 (pid=$new_pid)"
|
|
|
|
|
+ echo "$(date) $module restarted" >> "$HISTORY_FILE"
|
|
|
|
|
+ else
|
|
|
|
|
+ error "$module 可能启动失败,查看日志:"
|
|
|
|
|
+ echo "--- $start_log ---"
|
|
|
|
|
+ tail -30 "$start_log"
|
|
|
|
|
+ echo "--- end ---"
|
|
|
|
|
+ exit 1
|
|
|
|
|
+ fi
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+case "$TARGET" in
|
|
|
|
|
+ admin)
|
|
|
|
|
+ backup_and_copy "haha-admin"
|
|
|
|
|
+ start_service "haha-admin"
|
|
|
|
|
+ ;;
|
|
|
|
|
+ miniapp)
|
|
|
|
|
+ backup_and_copy "haha-miniapp"
|
|
|
|
|
+ start_service "haha-miniapp"
|
|
|
|
|
+ ;;
|
|
|
|
|
+ all)
|
|
|
|
|
+ backup_and_copy "haha-admin"
|
|
|
|
|
+ backup_and_copy "haha-miniapp"
|
|
|
|
|
+ start_service "haha-admin"
|
|
|
|
|
+ start_service "haha-miniapp"
|
|
|
|
|
+ ;;
|
|
|
|
|
+ *)
|
|
|
|
|
+ error "未知模块: $TARGET (可选: admin | miniapp | all)"
|
|
|
|
|
+ exit 1
|
|
|
|
|
+ ;;
|
|
|
|
|
+esac
|
|
|
|
|
+
|
|
|
|
|
+echo "========================================"
|
|
|
|
|
+info "部署完成"
|
|
|
|
|
+echo "========================================"
|