我想写个脚本,自动git pull, mvn编译打包,然后重启这个jar,但是又担心这个jar已经在启动了,重启不是端口冲突了吗

大家好,我是剽悍一小兔,独立开发者,副业搞钱尝试者,热爱技术分享,欢迎一起学习交流。我会每天分享编程技术、独立开发、行业咨询、思考感悟。

代表作:《JavaScript百炼成仙》

公众号:java小白翻身

小程序:速用百宝箱

设计一个包含进程检测、停止旧实例、编译打包、启动新实例的自动化脚本,并解决端口冲突问题。以下是完整脚本及关键逻辑说明:

自动化部署脚本(deploy.sh)

#!/bin/bash
set -euo pipefail  # 严格模式:遇到错误立即终止,未定义变量报错

# ==================== 可自定义配置 ====================
PROJECT_DIR="/path/to/your/project"  # 项目根目录(含pom.xml的目录)
JAR_NAME="your-app.jar"              # 编译后的jar包名称(如:demo-0.0.1-SNAPSHOT.jar)
JAVA_OPTS="-Xmx512m -Xms256m"       # JVM参数(根据服务器内存调整)
LOG_FILE="app.log"                   # 日志输出文件
PORT=8080                            # 应用端口(用于检测端口是否释放)
# ======================================================

# 函数:停止当前运行的jar进程
stop_jar() {
    echo "正在查找运行中的 $JAR_NAME 进程..."
    local pid=$(ps -ef | grep "java -jar $JAR_NAME" | grep -v grep | awk '{print $2}')
    
    if [ -n "$pid" ]; then
        echo "找到进程PID: $pid,尝试优雅停止..."
        kill -15 "$pid"  # 发送SIGTERM信号,允许进程优雅退出
        
        # 等待进程终止(最多30秒)
        local timeout=30
        local end_time=$(( $(date +%s) + timeout ))
        while [ $(date +%s) -lt $end_time ]; do
            if ! ps -p "$pid" > /dev/null; then
                echo "进程 $pid 已停止"
                return 0
            fi
            sleep 1
        done
        
        # 超时未停止则强制终止
        echo "优雅停止超时,强制终止进程 $pid..."
        kill -9 "$pid"
        sleep 2  # 确保进程资源释放
    else
        echo "未找到运行中的 $JAR_NAME 进程"
    fi
}

# 函数:检查端口是否已释放
check_port() {
    local port=$1
    echo "检查端口 $port 是否释放..."
    while true; do
        if ! lsof -i :$port > /dev/null; then
            echo "端口 $port 已释放"
            return 0
        fi
        echo "端口 $port 仍被占用,等待5秒..."
        sleep 5
    done
}

# 主流程
echo "===== 开始自动化部署 ====="

# 步骤1:进入项目目录
cd "$PROJECT_DIR" || { echo "项目目录 $PROJECT_DIR 不存在!"; exit 1; }

# 步骤2:拉取最新代码
echo "正在执行 git pull..."
git pull || { echo "git pull 失败!"; exit 1; }

# 步骤3:编译打包(跳过测试)
echo "正在执行 mvn clean package..."
mvn clean package -DskipTests || { echo "mvn 编译打包失败!"; exit 1; }

# 步骤4:停止旧进程
stop_jar

# 步骤5:确保端口释放(避免旧进程残留占用端口)
check_port "$PORT"

# 步骤6:启动新实例(后台运行+日志重定向)
echo "正在启动新实例 $JAR_NAME..."
nohup java $JAVA_OPTS -jar "target/$JAR_NAME" > "$LOG_FILE" 2>&1 &

echo "部署完成!新进程PID: $!"
echo "日志查看:tail -f $LOG_FILE"
echo "应用端口:$PORT"

脚本关键逻辑说明

1. 严格错误处理
  • • set -euo pipefail:脚本遇到错误(如命令执行失败)立即终止,避免因局部失败导致后续步骤出错。
  • • 每个关键步骤(如git pullmvn package)后检查退出状态(|| { ... }),失败时明确提示并终止脚本。
2. 停止旧进程(避免端口冲突核心逻辑)
  • • 优雅停止:先用kill -15(SIGTERM)通知进程正常退出(允许释放资源、保存状态)。
  • • 超时强制终止:若30秒内未停止(可能因死锁或资源占用),用kill -9强制终止,确保端口释放。
  • • 精准查找进程:通过grep "java -jar $JAR_NAME"匹配特定jar进程,避免误杀其他Java进程。
3. 端口释放检查
  • • 即使旧进程被终止,操作系统可能需要短暂时间回收端口(TIME_WAIT状态)。通过lsof -i :$PORT检测端口是否完全释放,避免新进程启动时提示“端口已被占用”。
4. 后台运行与日志记录
  • • 使用nohup避免终端关闭导致进程终止。
  • • > "$LOG_FILE" 2>&1将标准输出(stdout)和错误输出(stderr)统一重定向到日志文件,方便排查问题。

使用说明

  1. 1. 修改配置:替换脚本中PROJECT_DIR(项目路径)、JAR_NAME(jar包名称)、JAVA_OPTS(JVM参数)、PORT(应用端口)为实际值。
  2. 2. 赋予执行权限
    chmod +x deploy.sh
  3. 3. 执行脚本
    ./deploy.sh

扩展建议

  • • 添加健康检查:启动后通过curl检查应用是否正常响应(如curl http://localhost:8080/actuator/health),确保启动成功。
  • • 集成CI/CD:可将脚本添加到GitLab CI、Jenkins等工具,实现代码提交后自动触发部署。
  • • 日志分割:若日志文件过大,可结合logrotate定期切割日志。

如果需要进一步调整(如适配systemd服务、添加邮件通知等),可以告诉我具体需求,我会帮你优化脚本。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

剽悍一小兔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值