簡體   English   中英

在 Jenkins Pipeline 的 shell 腳本部分定義一個變量

[英]Defining a variable in shell script portion of Jenkins Pipeline

我正在嘗試動態定義一個我稍后在我的 Jenkins 管道的一些 shell 命令中使用的變量,但它拋出了一個異常。 我什至試圖從環境部分預定義變量無濟於事。 這是禁止的操作嗎? 我的另一個變量myVar似乎工作正常,但它在管道中是一個常量。

pipeline {
    agent any

   environment {
     py2Ana=""
     myVar="ABCDE"
   }
    stages {
        stage('Stage1') {
            steps {
                sh """
                    echo myVar=$myVar
                    echo Find Anaconda2 Python installation...
                    py2Ana=`which -a python | grep --max-count=1 anaconda2`
                    if [[ -z "$py2Ana" ]]; then
                        echo ERROR: must have a valid Anaconda 2 distribution installed and on the PATH for this job.
                        exit 1 # terminate and indicate error
                    fi
                """
            }
        }
    }

例外

groovy.lang.MissingPropertyException: No such property: py2Ana for class: groovy.lang.Binding
    at groovy.lang.Binding.getVariable(Binding.java:63)
    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:242)
    at org.kohsuke.groovy.sandbox.impl.Checker$6.call(Checker.java:288)
    at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:292)
    at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:268)
    at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:268)
    at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.getProperty(SandboxInvoker.java:29)
    at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.java:20)
    at WorkflowScript.run(WorkflowScript:21)

正如@jxramos 所說,Jenkins 正在嘗試解析腳本中的變量。 它將任何 $string 解釋為需要替換的變量。 解決方案是轉義腳本內變量的 $ ,如下所示:

pipeline { 
  agent any 
  stages {
    stage('test stage'){
      steps {
        sh """#!/bin/bash
            myvar=somevalue
            echo "The value is \$myvar"
        """
      }
    }
  }
}

如果您願意,Jenkins 在預處理步驟中似乎會強制執行變量替換優先級。 換句話說,沒有延遲擴展,就像在 Windows 批處理文件行為中發現的那樣, setlocal ENABLEDELAYEDEXPANSION 這解釋了發生了什么,這是我用來確定這一點的測試管道:

pipeline {
    agent any

   environment {
     py2Ana="DEFAULT"
   }
   stages {
       stage('Stage1') {
           steps {
                sh """
                    echo py2Ana=$py2Ana
                    py2Ana=Initialized
                    echo py2Ana Initialized=$py2Ana
                """
            }
        }
    }
}

這會產生以下控制台輸出...

Started by user unknown or anonymous
Running in Durability level: MAX_SURVIVABILITY
[Pipeline] node
[Pipeline] {
[Pipeline] withEnv
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Stage1)
[Pipeline] sh
[TestPipeline] Running shell script
+ echo py2Ana=DEFAULT
py2Ana=DEFAULT
+ py2Ana=Initialized
+ echo py2Ana Initialized=DEFAULT
py2Ana Initialized=DEFAULT
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

這帶來的另一個限制是,您確實不能在 Jenkins 聲明性管道腳本的sh部分使用動態變量,因為 Jenkins 將在執行之前首先嘗試解析所有變量。 因此以下總是會產生錯誤

sh """
   for filename in /tmp/**; do
      echo filename=$filename
   done
"""

錯誤是...

groovy.lang.MissingPropertyException: No such property: filename for class: groovy.lang.Binding

需要動態定義一個腳本(在找出一種將$轉義到文件的方法之后),或者在源代碼中已經有了它來執行。

錯誤本身似乎確實是由分配空字符串引起的。

但是:您真的需要在 Jenkinsfile 中定義該環境變量嗎? 對我來說,您似乎只想從 shell 腳本中設置和讀取變量。 但是它的編碼方式if [[ -z "$py2Ana" ]]; then if [[ -z "$py2Ana" ]]; then永遠不會選擇由 shell 腳本設置的值 - 它總是想使用 Jenkinsfile 中的屬性 - 這不起作用。

你可以使用if [[ -z "${env.py2Ana}" ]]; then if [[ -z "${env.py2Ana}" ]]; then對於可以修復該錯誤的 if 條件,但它仍然不會獲取前一行設置的值,但始終讀取 Jenkinsfile 中設置的空字符串。

為了解決這個問題,您可以將整個字符串用單引號括起來,例如(也許您甚至想擺脫myVar )...:

pipeline {
    agent any

    stages {
        stage('Stage1') {
            steps {
                sh '''
                    echo Find Anaconda2 Python installation...
                    py2Ana=`which -a python | grep --max-count=1 anaconda2`
                    if [[ -z "$py2Ana" ]]; then
                        echo ERROR: must have a valid Anaconda 2 distribution installed and on the PATH for this job.
                        exit 1 # terminate and indicate error
                    fi
                '''
            }
        }
    }
}

...或在$py2Ana之前添加一個反斜杠,例如:

pipeline {
    agent any

    stages {
        stage('Stage1') {
            steps {
                sh """
                    echo Find Anaconda2 Python installation...
                    py2Ana=`which -a python | grep --max-count=1 anaconda2`
                    if [[ -z "\$py2Ana" ]]; then
                        echo ERROR: must have a valid Anaconda 2 distribution installed and on the PATH for this job.
                        exit 1 # terminate and indicate error
                    fi
                """
            }
        }
    }
}

無論哪種方式都沒有在代碼中引用env.py2Ana我懷疑env.py2Ana中的environment塊仍然有意義 - 這就是我從示例中刪除它的原因。

只需為 py2Ana 添加一個值

environment {
     py2Ana="1234"
     myVar="ABCDE"
   }

如果您傳遞空字符串,它不會在環境中創建變量:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM