在Jenkins Pipeline的Shell脚本部分中定义变量

时间:2018-07-18 17:36:19

标签: jenkins 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)

5 个答案:

答案 0 :(得分:2)

如果您愿意,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

一个人需要动态定义一个脚本(在找出一种逃避$写入文件的方法之后),或者已经在源代码中将其执行。

答案 1 :(得分:1)

正如@jxramos所说,Jenkins试图解析脚本中的变量。它将任何$ string解释为需要替换的变量。 解决方法是转义脚本变量中的$,如下所示:

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

答案 2 :(得分:0)

变量之前必须带有 def

pipeline {
   agent none
   stages {
       stage("build") {
           def foo = "foo";
       }
   }
}

在我的情况下,我在阶段{}之前初始化了我的vars

def var = "var
stages {
   stage("build") {
       def foo = "foo";
   }
}

答案 3 :(得分:0)

只需将一个值添加到py2Ana

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

如果传递空字符串,则不会在环境中创建变量:)

答案 4 :(得分:0)

错误本身似乎真的是由分配空字符串引起的。

但是:您真的需要在Jenkinsfile中定义该环境变量吗? 在我看来,您似乎只想在Shell脚本中设置和读取变量。但是,它对if [[ -z "$py2Ana" ]]; then进行编码的方式永远不会采用shell脚本设置的值-它总是想使用Jenkinsfile中的属性-无效。

您可以将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,我怀疑Jenkinsfile中的environment块是否仍然有意义-这就是为什么我从示例中将其删除了。