在持续集成和持续部署(CI/CD)的实践中,自动化部署和版本回滚是确保服务高可用的关键步骤。本文将详细介绍如何在 Linux 服务器上实现以下目标

  1. 从 Git 仓库拉取最新代码
  2. 停止当前运行的 Spring Boot 服务
  3. 重新打包项目并部署到指定目录
  4. 支持一键版本回滚

一、准备工作

1.服务器环境要求
  1. Java 环境:安装 JDK 8+(确保 java -version 可运行)
  2. Maven:用于项目打包(确保 mvn -v 可运行)
  3. Git:用于代码拉取(确保 git --version 可运行)
  4. 目录权限:确保对 /opt/server 目录有读写权限。 
2. 项目结构 

 假设 Spring Boot 项目名为 dafu-admin,打包后的文件为 dafu-admin.jar,部署目录为 /opt/server。

二、自动化部署脚本 

  • 脚本功能
  • 从 Git 拉取最新代码
  • 停止正在运行的旧服务
  • 使用 Maven 重新打包项目
  • 备份旧版本
  • 部署新版本到 /opt/server
  • 启动新服务
  • 支持回滚到任意历史版本 

 三、使用说明

1. 首次部署

chmod +x deploy.sh  # 赋予执行权限

./deploy.sh         # 执行部署 
2. 后续更新 

直接运行脚本即可完成全流程:

./deploy.sh 
3. 版本回滚 
./deploy.sh rollback  # 回滚到最近一个备份版本 

 脚本内容 (deploy.sh)

#!/bin/bash
set -euo pipefail

# 配置区(按需修改)
PROJECT_DIR="/opt/server/"  # 项目目录
DEPLOY_DIR="/opt/server/project"            # 部署目录
DEPLOY_JAR_DIR="dafu-admin/target"            # 项目jar所在目录
BACKUP_DIR="/opt/server/backups"    # 备份目录
JAR_NAME="dafu-admin.jar"           # 固定JAR名称
MAX_BACKUPS=5                       # 最大保留备份数
BUILD_CMD="mvn clean package -DskipTests"  # 构建命令

# 日志配置
LOG_FILE="$DEPLOY_DIR/app.log"

# 创建必要目录
sudo mkdir -p "$BACKUP_DIR"
sudo chmod 755 "$BACKUP_DIR"

function backup_current_version() {
    if [ -f "$DEPLOY_DIR/$JAR_NAME" ]; then
        local timestamp=$(date +%Y%m%d%H%M%S)
        local backup_name="${JAR_NAME%.*}_$timestamp.${JAR_NAME##*.}"
        
        echo "正在备份当前版本..."
        sudo cp -v "$DEPLOY_DIR/$JAR_NAME" "$BACKUP_DIR/$backup_name"
        
        # 清理旧备份
        local backups=($(ls -t "$BACKUP_DIR"/*.jar 2>/dev/null))
        if [ ${#backups[@]} -gt $MAX_BACKUPS ]; then
            echo "清理旧备份..."
            for old_backup in "${backups[@]:$MAX_BACKUPS}"; do
                sudo rm -v "$old_backup"
            done
        fi
    fi
}

function rollback_version() {
    local backups=($(ls -t "$BACKUP_DIR"/*.jar 2>/dev/null))
    
    if [ ${#backups[@]} -eq 0 ]; then
        echo "错误:没有可用的备份版本!"
        exit 1
    fi
    
    local latest_backup="${backups[0]}"
    
    echo "正在回滚到版本:$(basename $latest_backup)"
    
    # 停止当前服务
    PID=$(pgrep -f "$JAR_NAME" || true)
    if [ -n "$PID" ]; then
        echo "停止当前进程 PID: $PID"
        kill "$PID"
        while ps -p "$PID" > /dev/null; do
            sleep 1
        done
    fi
    
    # 执行回滚
    sudo cp -vf "$latest_backup" "$DEPLOY_DIR/$JAR_NAME"
    
    # 启动服务
    echo "启动回滚版本..."
    cd "$DEPLOY_DIR"
    nohup java -jar "$JAR_NAME" > "$LOG_FILE" 2>&1 &
    sleep 3
    
    if ps -p $! > /dev/null; then
        echo "回滚成功!新PID: $!"
    else
        echo "回滚启动失败!检查日志:$LOG_FILE"
        exit 1
    fi
}

function deploy_new_version() {
    # 进入项目目录
    cd "$PROJECT_DIR" || {
        echo "错误:无法进入项目目录 $PROJECT_DIR"
        exit 1
    }

    # 1. 拉取最新代码
    echo "正在从Git仓库拉取更新..."
    git pull || {
        echo "错误:Git拉取失败!"
        exit 1
    }

    # 2. 停止正在运行的进程
    echo "正在停止当前服务..."
    PID=$(pgrep -f "$JAR_NAME" || true)
    if [ -n "$PID" ]; then
        echo "发现运行中的进程 PID: $PID"
        kill "$PID"
        while ps -p "$PID" > /dev/null; do
            sleep 1
        done
        echo "进程已停止"
    else
        echo "未找到运行中的服务"
    fi

    # 3. 构建项目
    echo "正在打包项目..."
    eval "$BUILD_CMD" || {
        echo "错误:项目构建失败!"
        exit 1
    }
       cd "DEPLOY_JAR_DIR" 
    # 4. 定位生成的JAR文件
    JAR_PATH="JAR_NAME"
    if [ -z "$JAR_PATH" ]; then
        echo "错误:未找到生成的JAR文件!"
        exit 1
    fi

    # 5. 备份当前版本
    backup_current_version

    # 6. 部署新版本
    echo "正在部署新版本到 $DEPLOY_DIR..."
    sudo cp -vf "$JAR_NAME" "$DEPLOY_DIR/$JAR_NAME"

    # 7. 启动服务
    echo "正在启动服务..."
    cd "$DEPLOY_DIR"
    nohup java -jar "$JAR_NAME" > "$LOG_FILE" 2>&1 &
    NEW_PID=$!
    
    sleep 3
    if ps -p "$NEW_PID" > /dev/null; then
        echo "服务启动成功!PID: $NEW_PID"
    else
        echo "错误:服务启动失败!"
        tail -n 20 "$LOG_FILE"
        exit 1
    fi
}

# 主流程
case "${1:-}" in
    rollback)
        rollback_version
        ;;
    *)
        deploy_new_version
        ;;
esac

echo "操作完成!"

Logo

一站式 AI 云服务平台

更多推荐