Jenkins流水线部署模板,编译、部署、关闭、回滚流水线脚本

1、Pipeline和Jenkinsfile

在这里插入图片描述

项目部署使用Pipeline的Jenkinsfile脚本代码方式会比基于界面配置好处:

  • 可以使用Git/SVN之类的版本工具把构建脚本也管理和控制;
  • 支持多人协作,也可以对脚本进行代码审核;
  • 构建脚本可以重用;

使用脚本的方式唯一缺点就是脚本构建相对界面配置会稍有一点难度,需要pipeline语法,pipeline支持groovy代码,可以基于groovy实现功能更强大的操作。

2、可以重用的构建脚本

这个构建脚本模板,定义了编译、部署、关闭、回滚操作,适用于大多数java项目,支持多服务器部署,可用于生产环境。
对于大多数项目,我们都是在安装Jenkins的这台服务器,完成编译和打包工具和制品管理,而在部署的服务器上,一般只安装java运行环境。对于大多公司可以使用Jenkins自带的archiveArtifactsa插件来对制品(部署文件、安装包等)管理,归档制品备份,回滚操作中可以直接使用归档的旧版本包,

2.1、配置多版本JDK

可以根据项目需要,配置多个版本的JAVA_HOME,比如本文是同时了OpenJDK8和OpenJDK11,构建时,可以通过在脚本中工具代码块中配置

tools {
	jdk 'JAVA_HOME8'  # 指定编译用的jdk版本
}

在这里插入图片描述

2.2、配置Maven

同样可以通过在脚本中工具代码块中配置:

tools {
     maven 'MAVEN_HOME'
}

在这里插入图片描述

2.3、远程服务器操作插件Publish Over SSH

可以在Linux shell中通过scp命令上传文件,ssh命令连接远程服务器操作脚本,参考代码如下,但是使用Publish Over SSH插件会更方便
Pipeline通过Linux shell上传文件和远程服务命令,注意需要先配置远程服务器免密登录。

stage('部署') {
    steps {
        script{
            sh "scp target/JApiTest-1.0.0_56.zip root@192.168.28.129:$upload_dir/JApiTest-1.0.0_56.zip"
            sh "ssh -tt root@192.168.28.129 << remotessh
                unzip -oq $upload_dir/${app_name}.zip -d ${deploy_dir}/${app_name}
                cd ${deploy_dir}/${app_name}
                chmod 0755 ./server.sh
                ./server.sh restart
                exit
                remotessh"
        }

    }
}

不推荐上边直接在Linux Shell命令上传和远程执行命令,建议使用Publish Over SSH或SSH Pipeline Steps的方式更好。
Publish Over SSH配置远程服务器连接信息,这里配置了两台部署服务器的连接信息。可以使用帐号密码的方式远程连接,也可以免密的方式远程连接。
在这里插入图片描述

2.4、创建Git帐号密码认证信息

在这里插入图片描述

2.5、创建PipeLine任务

在这里插入图片描述
创建的任务中,只需要在界面上配置Jenkinsfile文件所在的git仓库和在仓库中的具体目录就行了,其它信息不需要配置。Jenkinsfile代码版本化,更适合项目管理的需要,有能力公司也可以对Jenkinsfile代码进行评审。
在这里插入图片描述

2.6、PipeLineJenkinsfile脚本代码

完成2.1-2.5配置,就可以在具体的流水线代码上使用这些配置了,为了获取pom.xml文件中的版本,也使用groovy代码写了个version(file)获取版本号的方法供脚本调用。完整的流水线代码如下:

/**
* 获取maven项目版本号
*/
def version(file){
    def version = ''
    if(fileExists(file)){
        def data = readFile(file: file)
        def lines = data.readLines()
        def isProject = false;
        def isParent = false;
        for (line in lines) {
            if(line.indexOf("<project") > -1){
                isProject = true
            }
            if(isProject == true && line.indexOf("<version>") > -1){
                def start = line.indexOf("<version>");
                def end = line.indexOf("</version>");
                version = line.substring(start + 9,end);
                break;
            }
        }
    }
    return version
}

def build(){
    checkout([$class: 'GitSCM', branches: [[name: '*/master']], extensions: [],userRemoteConfigs:[[
                                                                                                        credentialsId: 'gitee', url: 'https://gitee.com/penngo/XXJApiTest.git']]])
    app_version =version(source_dir + '/pom.xml')
    env.app_name_version ="${app_name}-${app_version}"
    sh("""
        java -version
        mvn clean package
    """.replace("    ", ""))
    sh([
            "cd ${source_dir}/target",
            "cp -f ../server.sh server.sh",
            "zip -q -r ${app_name_version}_${BUILD_ID}.zip ${app_name_version}.war server.sh"
    ].join("\n"))
}

def deploy(servers, build_id_temp){
    def build_id = build_id_temp == '' ? readFile(file: "build_id.txt") : build_id_temp;
    sh("""
        cp -f ${WORKSPACE}/../../jobs/${app_name}/builds/${build_id}/archive/target/*_${build_id}.zip ${app_name}.zip
    """.replace("\t",""));

    for(ip in servers.tokenize(",")){
        echo "=====ssh_ip:" + ip
        sshPublisher(
                publishers: [
                        sshPublisherDesc(
                                configName: "${ip}",
                                transfers: [
                                        sshTransfer(cleanRemote: false,
                                                excludes: '',
                                                execCommand: """
                                                        unzip -oq $upload_dir/${app_name}.zip -d ${deploy_dir}/${app_name}
                                                        cd ${deploy_dir}/${app_name}
                                                        chmod 0755 ./server.sh
                                                        ./server.sh restart
                                                """.replace('    ',''),
                                                execTimeout: 120000,
                                                flatten: false,
                                                makeEmptyDirs: false,
                                                noDefaultExcludes: false,
                                                patternSeparator: '[, ]+',
                                                remoteDirectory: "${upload_dir}",
                                                remoteDirectorySDF: false,
                                                removePrefix: "",
                                                sourceFiles: "${app_name}.zip")
                                ],
                                usePromotionTimestamp: false,
                                useWorkspaceInPromotion: false,
                                verbose: true)
                ])
    }
}

def rollback(servers, build_number){
    deploy(servers, build_number)
}

pipeline {
    agent any
    tools {
        maven 'MAVEN_HOME'
        jdk 'JAVA_HOME8'
    }
    options {
        buildDiscarder(logRotator(numToKeepStr: "10"))
    }
    environment{
        source_dir="${WORKSPACE}/JApiTest"
        jenkinsfile_dir="${WORKSPACE}"
        jenkinsfile_job_dir="${WORKSPACE}/../../JApiTest"
        app_version=version(source_dir + '/pom.xml')
        app_name="JApiTest"
        app_name_version="${app_name}-${app_version}"
        deploy_dir="/data/app"
        upload_dir="/data/upload"

    }
    parameters {
        choice(name: 'app', choices:['JApiTest'],description: '应用(请选择需要操作的应用:JApiTest)')
        choice(name: 'select', choices:[
                '请选择',
                '编译',
                '部署',
                '回滚',
        ],description: '操作(请选择操作:编译、部署、回滚)')

        extendedChoice(description: '服务器', value: '192.168.28.129,192.168.28.132',
            descriptionPropertyValue: '192.168.28.129(测试),192.168.28.132(正式)',
            multiSelectDelimiter: ',', name: 'servers', quoteValue: false, saveJSONParameterToFile: false, type: 'PT_CHECKBOX', visibleItemCount: 5)
        string(
                description: """回滚版本号""",
                name: 'roll_number',
                trim: true
        )
    }

    stages {
        stage('编译') {
            when {
                expression { params.select.trim() == "编译" }
            }
            steps {
                dir("${source_dir}"){
                    script {
                        build()
                    }
                }
                writeFile(file: "build_id.txt", text: "${BUILD_ID}")
            }
        }

        stage('部署') {
            when {
                expression { "${params.select}".trim() == "部署" }
            }
            steps {
                script {
                    deploy(params.servers, '')
                }
            }
        }

        stage('回滚') {
            when {
                expression { "${params.select}".trim() == '回滚' }
            }
            steps {
                script {
                    rollback(params.servers, params.roll_number)
                }
            }
        }
    }
    post {
        success{
            script {
                if(params.select.trim() == "编译"){
                    dir("${source_dir}"){
                        archiveArtifacts artifacts: "target/${app_name_version}_${BUILD_ID}.zip", fingerprint: false
                    }
                }
            }

        }
    }
}

配合运行的Linux脚本server.sh

#!/bin/bash -il
export JAVA_HOME=/usr/lib/jvm/bellsoft-java8-full.x86_64
export PATH=$JAVA_HOME/bin:$PATH
java -version

APP_NAME="JApiTest"
JAR_NAME="JApiTest-1.0.0.jar"
JAVA_OPTS="-Xmx2G -XX:+UseG1GC"

start() {
	pid=`ps -ef | grep "$JAR_NAME" | grep -v grep | awk '{print $2}'`
	if [ -z $pid ]; then
	  export JENKINS_NODE_COOKIE=dontKillMe
    nohup java $JAVA_OPTS -jar $JAR_NAME 2>&1 &
    sleep 3
    pid=`ps -ef | grep "$JAR_NAME" | grep -v grep | awk '{print $2}'`
    if [ -z $pid ]; then
      echo ".....service ${JAR_NAME} is run error....."
    else
      echo ""
      echo ".....Service ${JAR_NAME} is starting!pid=${pid}....."
      echo "........................Start successfully!........................."
    fi
	else
		echo ""
		echo "Service ${JAR_NAME} is already running,it's pid = ${pid}"
		echo ""
	fi
}

stop() {
	pid=`ps -ef | grep "$JAR_NAME" | grep -v grep | awk '{print $2}'`
	if [ -z $pid ]; then
    echo "Service ${JAR_NAME} is not running!"
	else
		kill -9 $pid
		echo "Service stop successfully!pid:${pid} been killed"
	fi
}

restart() {
	echo ""
	echo ".............................Restarting.............................."
	stop
	start
	echo "....................Restart successfully!..........................."
}

if [ ! -n "$1" ] ;then
 echo "Usage: $0 {start|stop|restart}"
elif [ $1 = "start" ];then
 start
elif [ $1 = "stop" ];then
 stop
elif [ $1 = "restart" ];then
 restart
fi

2.7、构建效果

使用Pipeline脚本方式部署,必须先执行一次后,才能出现2.7.1参数可选界面,如果未执行过,默认是下边在界面:
在这里插入图片描述

2.71、编译

在这里插入图片描述

2.72、部署

在这里插入图片描述

2.73、回滚

构建前需要填入有归档文件的构建任务号。
在这里插入图片描述

2.8、全部构建结果

构建任务中有下载图标的都表示这个构建任务有归档文件。
在这里插入图片描述

  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

penngo

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

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

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

打赏作者

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

抵扣说明:

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

余额充值