1. 程式人生 > >[轉] Jenkins pipeline 踩坑集合

[轉] Jenkins pipeline 踩坑集合

[From] https://testerhome.com/topics/10328

 

前言

最近由於專案需要,接觸到了Jenkins 2.0版本,其中最重要的特性就是提供了對pipeline的支援。
簡單的來說,就是把Jenkins1.0版本中,Project中的相關配置資訊,如SVN/Git的配置,Parameter的配置等都變成Code,即Pipeline as Code。
這樣的優勢為可以通過寫程式碼的形式配置Project,且Jenkins中內建了常用的steps。實現了構建步驟程式碼化、構建過程檢視化。
其他的Jenkins基礎這裡不多說了,這裡主要介紹最近遇到的問題及其處理方法。一方面是自己總結和整理一下,另一方面也可以供他人蔘考,少踩坑。

 

選擇Declarative Pipeline還是Scripted Pipeline

最開始的Pipeline plugin,支援的只有一種指令碼型別,就是Scripted Pipeline;
Declarative Pipeline為Pipeline plugin在2.5版本之後新增的一種指令碼型別,與原先的Scripted Pipeline一樣,都可以用來編寫指令碼。

使用哪一種指令碼格式呢,我又糾結了,也查詢了些資料。
https://stackoverflow.com/questions/43484979/jenkins-scripted-pipeline-or-declarative-pipeline


http://jenkins-ci.361315.n4.nabble.com/Declarative-pipelines-vs-scripted-td4891792.html

最後,我還是選擇了Declarative Pipeline,這也是後續Open Blue Ocean所支援的型別。
相對而言,Declarative Pipeline比較簡單,如果Groovy很熟的,用Scripted Pipeline可能更順手。
另外,Declarative Pipeline中,是可以內嵌Scripted Pipeline程式碼的。

 

設定和獲取執行引數

原先在Jenkins 1.0的時候,常用的一個設定就是“ "This build is parameterized",通過獲取引數值,執行後續相關的判斷及操作。
在pipeline中,可以這樣設定:

#!/usr/bin/env groovy
pipeline{
    agent none
    options{
        disableConcurrentBuilds()
        skipDefaultCheckout()
        timeout(time: 1, unit: 'HOURS')
        timestamps()
    }
    parameters{
        string(name: 'PERSON', defaultValue: 'among中文', description: '請輸入中文')
        booleanParam(name: 'YESORNO', defaultValue: true, description: '是否釋出')
    }
    stages{
    stage('test stage')
    {
      agent
      {
          label 'master' 
      }
      steps
       {
          echo 'Hello, stage1'
          echo "Hello ${params.PERSON}"
          echo "Hello ${env.PERSON}"
      scrip
          {
            def input = params.YESORNO
            if (input)
            {
              echo "you input is ${input},to do sth"
            }
            else
            {
              echo "you input is ${input},nothing to do"
            }
          }
       }
    }
}

 

環境變數的問題

通過Jenkins 執行相關sh的時候,環境變數中,不會預設繼承/etc/profile 和 ~/.profile 等環境變數。
這個時候就很麻煩了,尤其在一些依賴環境變數操作的sh指令碼時。

可以這樣來做,一是在增加node節點時,自己設定環境變數,如:

 

 

也可以在程式碼中這麼寫。寫 withEnv ,或是直接在shell中先source profile檔案。然後在執行相關命令。

steps
{
    withEnv(['TPS=amtps']) {
  // do sth
  }
 // 
    sh 'source /etc/profile && source ~/.bash_profile && env'
    dir('/root')
    {
      sh '(source /etc/profile;source ~/.bash_profile;sh ./ee.sh)'
    }
}

 

Jenkins中nohup後進程還是起不來的問題

在普通的shell環境中,nohup,並且& 某個程式後,會拋到後臺執行,在退出當前shell環境後,程式依然可以執行。
但是在Jenkins中,通過nohup,且使用&之後,step結束後,執行的程式還是會退出,導致程式起不來。

嘗試和驗證了很多方法,後面都是這樣解決的。
修改JENKINS_NODE_COOKIE的值,這樣後續結束的時候,後面的sh程式就不會被kill掉了。
適用版本:Jenkins 2.46版本,版本如差異較大,可能不一致。當時為了解決這個問題,折騰了很久,找的資料也比較老了,很多都沒用,特定記錄一下。

steps
  {
    sh 'JENKINS_NODE_COOKIE=dontKillMe nohup python3 /home/among/pj/my_py/monitor/amon/amon.py >/tmp/run.log 2>&1 &'
  }

 

shell出錯後繼續,取shell輸出值。

這2個比較簡單,看例子就知道了。

steps
{
 sh returnStatus: true, script: "ps -ef|grep amon|grep -v grep|awk '{print \$2}'|xargs kill -9"
 script
 {
   def pid = sh returnStdout: true ,script: "ps -ef|grep amon|grep -v grep|awk '{print \$2}'"
   pid = pid.trim()
   echo "you input pid is ${pid},to do sth"
   sh "kill -9 ${pid}"
 }

}

 

以上就是最近遇到的一些問題,後續遇到了,我再補充吧。
一些地方有可能存在問題或有更好的解決方法,歡迎大家提出和完善。