• 2.Jenkins之Pipeline使用


    概念

    是一套运行在 Jenkins 上的工作流框架,将原来独立运行于单个或者多个节点 的任务连接起来,实现单个任务难以完成的复杂流程编排和可视化的工作。

    优势

    代码:Pipeline以代码的形式实现,通常被检入源代码控制,使团队能够编辑,审查和迭代其传送流程。
    持久:无论是计划内的还是计划外的服务器重启,Pipeline都是可恢复的。
    可停止:Pipeline可接收交互式输入,以确定是否继续执行Pipeline。
    多功能:Pipeline支持现实世界中复杂的持续交付要求。它支持fork/join、循环执行,并行执行任务的功能。
    可扩展:Pipeline插件支持其DSL的自定义扩展 ,以及与其他插件集成的多个选项。

    插件安装

    需要安装插件Pipeline

    安装后,在Jenkins中"新建Item"时会出现一个选项

    image-20220410135901485

    PipeLine语法

    #声明式:
    pipeline {
        agent any
        stages { #整个流水线的所有执行阶段。通常stages只有1个,里面包含多个stage
            stage('拉取代码' ) { #流水线中的某个阶段,可能出现多个。一般分为拉取代码,编译构建,部署等阶段。
                steps { #代表一个阶段内需要执行的逻辑。steps里面是shell脚本,git拉取代码,ssh远程发布等任意内容
                    echo '拉取代码'
                }
            }
            stage('编译代码 ') {
                steps {
                    echo '编译代码'
                }
            }
            stage('发布运行 ') {
                steps {
                    echo '发布运行'
                }
            }
        }
    }
    #脚本式:
    node {
        stage('拉取代码' ) {
            echo '拉取代码'
        }
        stage('编译代码 ') {
            echo '编译代码'
        }
        stage('发布运行 ') {
            echo '发布运行'
        }
    }
    
    

    实现拉取->编译->部署

    整体配置项没变,和第一篇一样,只不过展现的形式变了

    最终生成好的PipeLine

    不论是声明式还是脚本式,实际执行的内容一样,只不过结构不同

    node {
        stage('拉取代码' ) {
            checkout([$class: 'GitSCM', branches: [[name: '*/master1']], extensions: [], userRemoteConfigs: [[credentialsId: '1dabcacf-ffda-4c45-ad9b-32f9a640f4d9', url: 'https://gitee.com/RollBack2010/jekins-study.git']]])
        }
        stage('编译代码 ') {
            sh 'mvn clean package'
        }
        stage('发布运行 ') {
        sshPublisher(publishers: [sshPublisherDesc(configName: 'jarPath', transfers: [sshTransfer(cleanRemote: false, excludes: '', 		execCommand: '''cd /usr/local/project
    ./start.sh''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: 'target/', sourceFiles: 'target/demo-0.0.1-SNAPSHOT.jar')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false), sshPublisherDesc(configName: 'jarPath1', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '''cd /usr/local/project1
    ./start.sh''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: 'target/', sourceFiles: 'target/demo-0.0.1-SNAPSHOT.jar')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])     
        }
    }
    

    命令生成方式

    进入“流水线语法”生成页面

    image-20220410152909767

    拉取

    image-20220410153031353

    image-20220410153133005

    编译

    image-20220410153234422

    部署

    image-20220410153432237

    执行Build

    会完成下载、编译、部署、启动流程

    PipeLine脚本存放到项目中

    以上都是将命令存放到Jenkins中,这样无法记录脚本修改记录,也容易丢失,所以将脚本放到项目中,通过git进行管理

    创建Jenkinsfile

    存放到项目根目录,名字也可以改,不过Jenkins默认找这个,文件内容就是上面的脚本内容

    image-20220410154534691

    Jenkins中修改配置

    image-20220410154817695

    执行Build

    会完成下载、编译、部署、启动流程

    通过参数构建

    上面拉取代码的分支都是写死在Jenkinsfile中,现在把这个设置为传入变量

    第一步,jenkins项目配置

    image-20220410194940616

    第二步,修改Jenkinsfile脚本

      #*/master1 -> */${branch}
      #由
      checkout([$class: 'GitSCM', branches: [[name: '*/master1']], extensions: [], userRemoteConfigs: [[credentialsId: 'ff8ba3ca-be5f-4535-bb37-08de5ef208f9', url: 'https://gitee.com/RollBack2010/jekins-study.git']]])
      #修改为
     checkout([$class: 'GitSCM', branches: [[name: '*/${branch}']], extensions: [], userRemoteConfigs: [[credentialsId: 'ff8ba3ca-be5f-4535-bb37-08de5ef208f9', url: 'https://gitee.com/RollBack2010/jekins-study.git']]])
    

    第三步,使用

    image-20220410195153859

    对于在“片段生成器”中未提供的插件使用

    我想实现,拉取代码编译完成后,在部署前,先去对应服务器上把正在运行的服务停止,否则直接启动会报端口占用

    第一步,安装插件SSH Pipeline Steps

    image-20220410200346979

    第二步,发现插件未提供代码片段生成

    image-20220410200527018

    第三步,打开对应的README

    根据文档及各种搜索引擎实现

    本次实现的完整Pipeline脚本

    #第一步.先定义要去哪台服务器上执行停止脚本
    def remote = [:]
    remote.name = 'test' #起个名字
    remote.host = '192.168.0.104' #服务器ip
    remote.user = 'root'
    remote.password = '123'
    remote.allowAnyHosts = true
    
    pipeline {
        agent any
        stages {
            stage('拉取代码' ) {
                steps {
                    checkout([$class: 'GitSCM', branches: [[name: '*/${branch}']], extensions: [], userRemoteConfigs: [[credentialsId: 'ff8ba3ca-be5f-4535-bb37-08de5ef208f9', url: 'https://gitee.com/RollBack2010/jekins-study.git']]])
                }
            }
            stage('编译代码 ') {
                steps {
                    sh 'mvn clean package'
                }
            }
            #第二步.添加一个管道
            stage('停止服务 ') {
                steps {
                #执行对应服务器上的一个脚本
                    sshCommand remote: remote, command: "bash /usr/local/project/stop.sh"
                }
            }
            stage('发布运行 ') {
                steps {
                    sshPublisher(publishers: [sshPublisherDesc(configName: 'jarPath', transfers: [sshTransfer(cleanRemote: false, excludes: '', 		execCommand: '''cd /usr/local/project
    ./start.sh''', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: 'target/', sourceFiles: 'target/demo-0.0.1-SNAPSHOT.jar')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])     
                }
            }
        }
    }
    

    stop.sh脚本内容

    #!/bin/sh -l
    
    #在jenkins "Execute shell"中先刷新环境变量,否则会报各种找不到命令
    source /etc/profile
    
    #定义一个全局变量,用于存放服务的进程
    processNum
    #定义个函数,用于获得进程,并将进程赋值给上面定义的变量
    #这个函数逻辑为:
    #	1.通过jps -l命令,获得所有运行的java进程
    #	2.通过awk命令,查询jar包叫 “project-0.0.1-SNAPSHOT.jar”的(此处可改成各种正则条件匹配)
    #	3.通过cut命令,根据“ ”切分awk匹配出来的记录,然后获得进程
    function checkProcessNum()
    {
            processNum=$(jps -l | awk -F " " '/demo-0.0.1-SNAPSHOT.jar/' | cut -d " " -f 1)
    }
    #调用一下函数,获得进程
    checkProcessNum
    
    echo "当前运行进程号为:"$processNum"执行kill命令"
    
    #执行kill命令,当然,这块应该再加个if判断进程是否存在更好
    kill $processNum
    
    echo "kill命令已执行,循环检查是否正常停止"
    #isDown:0:服务未停 1:服务已停
    isDown=0
    
    #循环检查是否停止,因为可能有线程还未执行完,无法停止
    while [ $isDown -eq 0 ]
            do
              echo "每隔1秒查询下项目端口是否存在,存在说明还没停止"
              sleep 1s
              #每等待1秒调用函数查询进程是否存在
              checkProcessNum
    
              if [ ! $processNum ]
                    then
                    #进程终止了,停止循环
                            echo "服务停止了"
                            isDown=1
              elif [  $processNum ]
                    then
                            echo "服务还在运行中"
              fi
              done
    
    echo "服务已停止"
    
  • 相关阅读:
    Python的词法分析与语法分析
    使用svn log确定分支创建的时间点
    Python的作用域
    SVN的版本日期
    理解SVN关键词BASE,HEAD,COMMITTED,PREV
    SVN的属性
    EL表达式 (详解)
    java jsp el fn
    java防止表单重复提交
    数据库的事务处理
  • 原文地址:https://www.cnblogs.com/rb2010/p/16195443.html
Copyright © 2020-2023  润新知