当前位置: 首页 > java >正文

编写后端JAR包蓝绿发布脚本

前端发布脚本的功能

  1. 保留每一个发布版本,防止新版本异常,方便回撤
  2. 用户无感知,防止发布过程中的宕机

原理:
发布的JAR包只是一个软连接,新的JAR启动正常后,切换软连接指向即可。蓝绿JAR包绑定端口不同,所以nginx也需要修改反向代理指向路径

发布逻辑

  1. 上传新JAR包文件到指定目录
  2. 将新JAR包重命名为日期_时间.JAR
  3. 通过命令,运行日期_时间.JAR
  4. 通过spring-boot-actuator健康判断来判断 日期_时间.JAR 是否运行正常
  5. 运行正常,切换软连接指向 + 更改nginx反向代理配置端口

脚本执行代码:
注意:充分测试脚本后再上生产环境,禁止使用root账号执行脚本,强制要求切换到deploy用户,不熟悉脚本的请手动操作

deploy用户创建,可以查看文章 生成环境项目目录规划

看懂脚本最好也结合 生成环境项目目录规划 来看

#!/usr/bin/env bash
set -euo pipefail# ---- 仅允许 deploy 执行 ----
RUN_AS="$(id -un || true)"
if [[ "$RUN_AS" != "deploy" ]]; thenecho "❌ 本脚本仅允许 deploy 用户执行。当前用户:$RUN_AS"echo "   请使用:su - deploy"exit 126
fi# ===== 固定配置 =====
JAR_SRC="/www/wwwroot/mes_saas/api/upload/mes-saas.jar"   # 固定上传路径
BASE="/www/wwwroot/mes_saas"
REL="${BASE}/api/releases"                                # 版本库根
NGX_BACKEND="${BASE}/nginx/backend.conf"                  # 切流文件
PORTS=("16888" "16889")
HEALTH_PATH="/actuator/health"
HEALTH_WAIT=25# 外部程序绝对路径(按你的机器确认)
SUDO="/usr/bin/sudo"
JAVA_SERVICE="/usr/bin/java-service"
NGINX="/usr/bin/nginx"
CURL="/usr/bin/curl"
SS="/usr/sbin/ss"
PGREP="/usr/bin/pgrep"
TEE="/usr/bin/tee"
# ====================# 0) 基础校验
[[ -f "$JAR_SRC" ]] || { echo "❌ 未找到上传的 jar 包: $JAR_SRC"; exit 1; }
real_in_prefix() { [[ "$(realpath -m "$1")" == "$(realpath -m "$2")"* ]]; }
real_in_prefix "$REL" "$BASE" || { echo "❌ releases 路径越界:$REL"; exit 1; }
real_in_prefix "$NGX_BACKEND" "$BASE" || { echo "❌ backend.conf 路越界:$NGX_BACKEND"; exit 1; }# 工具函数
listening_by_java() {local port="$1"$SS -lntp 2>/dev/null | grep -q ":$port " && $PGREP -f "java .*--server.port=$port" >/dev/null
}
health_ok() {local port="$1"$CURL -fsS "http://127.0.0.1:${port}${HEALTH_PATH}" | grep -q '"status":"UP"'
}
start_or_restart() {local port="$1"if listening_by_java "$port"; then$SUDO "$JAVA_SERVICE" "mes_saas_${port}" restartelse$SUDO "$JAVA_SERVICE" "mes_saas_${port}" startfi
}
stop_port() { local p="$1"; $SUDO "$JAVA_SERVICE" "mes_saas_${p}" stop || true; }# 1) 检测当前线上端口 ACTIVE
ACTIVE=""
for p in "${PORTS[@]}"; doif listening_by_java "$p"; then ACTIVE="$p"; break; fi
done
[[ -z "$ACTIVE" ]] && ACTIVE="${PORTS[0]}"# 2) 选择目标端口 TARGET(另一个)
TARGET="${PORTS[0]}"
[[ "$ACTIVE" == "${PORTS[0]}" ]] && TARGET="${PORTS[1]}"echo "当前线上端口: $ACTIVE  ->  目标端口: $TARGET"# 3) 准备版本目录与软链(给 TARGET)
mkdir -p "${REL}/${TARGET}"
TAG="$(date +%Y%m%d_%H%M%S)"
VER_JAR="${REL}/${TARGET}/mes-saas-${TAG}.jar"
LINK_JAR="${REL}/${TARGET}/mes-saas.jar"mv "$JAR_SRC" "$VER_JAR"
ln -sfn "$VER_JAR" "$LINK_JAR"
echo "已更新 ${LINK_JAR} -> $(basename "$VER_JAR")"# 4) 先启动/重启 目标端口(旧版本仍在线上承载)
echo "启动(或重启) 目标端口 ${TARGET}"
start_or_restart "$TARGET"# 5) 健康检查(未通过就终止,不切流,旧版本继续在线)
echo -n "健康检查: http://127.0.0.1:${TARGET}${HEALTH_PATH} ..."
for i in $(seq 1 "$HEALTH_WAIT"); doif health_ok "$TARGET"; then echo " OK"; break; fisleep 1if [[ $i -eq $HEALTH_WAIT ]]; thenecho " 失败,保持 $ACTIVE 在线,不切换"exit 1fi
done# 6) 健康通过后,切 Nginx 到 TARGET(再 reload)
echo "set \$mes_backend http://127.0.0.1:${TARGET};" | $SUDO $TEE "$NGX_BACKEND" >/dev/null
$SUDO "$NGINX" -t
$SUDO "$NGINX" -s reload
echo "Nginx 已切到端口: ${TARGET}"# 7) 最后再停止旧端口(ACTIVE)
if [[ "$ACTIVE" != "$TARGET" ]]; thenecho "停止旧端口 ${ACTIVE}"stop_port "$ACTIVE"
fiecho "✅ 发布完成。线上端口: ${TARGET}"
最后注意

nignx这里有一个坑,查看文章:nginx采用反向代理的时候使用变量的坑

http://www.xdnf.cn/news/20199.html

相关文章:

  • 23种设计模式——代理模式(Proxy Pattern)详解
  • 【使用goto统计输入数的奇偶数量】2022-10-28
  • 人工智能时代职能科室降本增效KPI设定全流程与思路考察
  • 【高分论文密码】大尺度空间模拟与不确定性分析及数字制图技术应用
  • 为什么动态视频业务内容不可以被CDN静态缓存?
  • [ubuntu][C++]onnxruntime安装cpu版本后测试代码
  • 扫描件、PDF、图片都能比对!让文档差异无所遁形
  • TDengine 时间函数 TODAY() 用户手册
  • Next.js 介绍:为什么选择它来构建你的下一个 Web 应用?
  • 开发环境 之 编辑器、编译器、IDE梳理
  • 深度解读:PSPNet(Pyramid Scene Parsing Network) — 用金字塔池化把“场景理解”装进分割网络
  • 【c++】c++第一课:命名空间
  • uni-app 项目 iOS 上架效率优化 从工具选择到流程改进的实战经验
  • 从零开始的python学习——字典
  • 永磁同步电机负载估计算法--非线性扩张状态观测器
  • 看见世界的另一种可能:Deepoc星眸(StarGaze)如何为视障生活带来曙光
  • Onlyoffice集成与AI交互操作指引(Iframe版)
  • 美团发布 | LongCat-Flash最全解读,硬刚GPT-4.1、Kimi!
  • 标签系统的架构设计与实现
  • Oracle软件在主机平台的应用(课程下载)
  • 请求超过Spring线程池的最大线程(处理逻辑)
  • 企业级项目管理方法设计指南
  • Scikit-learn Python机器学习 - 特征预处理 - 标准化 (Standardization):StandardScaler
  • 音视频面试题集锦第 38 期
  • 电影级文字生视频核心代码手册
  • CASToR 生成的文件进行转换
  • 1.数据库介绍
  • java面试:有了解过数据库事务吗,能详细讲一讲么
  • 四川地区燃气从业人员考试题库及答案
  • Redis中的hash数据类型