如何在Jenkins流水线作业中列出所有的`env`属性?

158
给定一个Jenkins构建流水线,Jenkins会将一个变量env注入到node{}中。变量env保存着环境变量和对应的值。 我想在Jenkins流水线中打印出所有env属性。然而,我事先不知道所有env属性。 例如,可以使用以下代码打印环境变量BRANCH_NAME
node {
    echo "BRANCH_NAME is " + ${env.BRANCH_NAME}
    ...

但是,我不知道所有的变量提前。我希望有能够处理这种情况的代码,类似于:
node {
    for(e in env){
        echo e + " is " + ${e}
    }
    ...

会回响出类似的声音
 BRANCH_NAME is myBranch2
 CHANGE_ID is 44
 ...

我在这个例子中使用了Jenkins 2.1。

3
看起来这是与 https://dev59.com/uFoV5IYBdhLWcg3wAqvy 相同的内容。 - Krzysztof Krasoń
3
据我所知,env只是封装了环境变量。我认为你不能通过循环来遍历它。在Linux上尝试使用'sh env',在Windows上使用'bat set'。 - Dominik Gebhart
3
根据我下面的评论,@Renato和@Jayan,env.each { name, value -> println "Name: $name -> Value $value" }会打印出Name: org.jenkinsci.plugins.workflow.cps.EnvActionImpl@45c2d1ee -> Value null - JamesThomasMoon
1
@JamesThomasMoon1979 这是因为 Pipeline 打破了 Groovy 闭包。如果你使用旧的 Java 风格编写(也就是 new ClassName() { ... }),那么它应该能够正常工作。或者你可以在一个标记有 @NonCPS 的方法中运行它,这样闭包也可以在其中工作。 - Daniel C. Sobral
2
'env' 对象不是一个映射,而是某个类对象。 我在 Jenkins 管道脚本中尝试了它。 像 ".each()" 这样的调用将导致 "Name: org.jenkinsci.plugins.workflow.cps.EnvActionImpl@633862d -> Value null",而像 ".containsKey(...)" 这样的调用将导致 "hudson.remoting.ProxyException: groovy.lang.MissingMethodException: No signature of method: org.jenkinsci.plugins.workflow.cps.EnvActionImpl.containsKey() is applicable for argument types: (java.lang.String) values: [...]"。 - Alexander Stohr
显示剩余2条评论
21个回答

158

4
printenv 是一个仅打印环境变量的 shell 命令,与 Jenkins 无关。不带参数时,它相当于不带参数的 env 命令。我很确定在 DCL 或者脚本管道中使用 sh 'printenv | sort' 是可行的。 - simon.watts
2
经过测试,sh 'printenv | sort' 确实适用于 Jenkins 声明性流水线。同样适用的是 sh 'env | sort'(均在 Jenkins ver. 2.46.1 上进行了测试)。最初我提到 sh 'printenv' 是因为它出现在官方 Jenkins 文档中。 - Wimateeka
1
如果你不需要returnStdout:true,那么你就不需要echo;它只是打印了shell脚本已经打印的内容。 - Ed Randall

95

26
在Windows下,将sh替换为bat,将env替换为set - jmkgreen
1
对于“sh”情况,我使用“env | sort”,因为键没有排序让我感到疯狂。 - Jeff Hutton
1
在Windows系统下:echo bat(returnStdout: true, script: 'set') - Noman Chali

43
以下内容是有效的:
@NonCPS
def printParams() {
  env.getEnvironment().each { name, value -> println "Name: $name -> Value $value" }
}
printParams()

请注意,在首次执行时,它很可能会失败,并要求您批准在Jenkins沙箱中运行各种Groovy方法。这可以在“管理Jenkins / 进程脚本批准”中完成。

我得到的列表包括:

  • BUILD_DISPLAY_NAME
  • BUILD_ID
  • BUILD_NUMBER
  • BUILD_TAG
  • BUILD_URL
  • CLASSPATH
  • HUDSON_HOME
  • HUDSON_SERVER_COOKIE
  • HUDSON_URL
  • JENKINS_HOME
  • JENKINS_SERVER_COOKIE
  • JENKINS_URL
  • JOB_BASE_NAME
  • JOB_NAME
  • JOB_URL

1
这个不起作用:java.lang.UnsupportedOperationException: each on a CPS-transformed closure is not yet supported - bsky
5
你确定已经包含了 @NonCPS 吗? - Joe C.
1
这是最佳答案,因为它可以在节点块之外工作。非常感谢您的帮助。 - Gi0rgi0s
2
不是一个好的解决方案, env.getEnvironment() 在管道脚本中没有被列入白名单:org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use method org.jenkinsci.plugins.workflow.support.actions.EnvironmentAction getEnvironment - haridsv
1
请注意,第一次执行时很可能会失败,并且需要您批准在Jenkins沙盒中运行各种Groovy方法。 这可以在“管理Jenkins/进程脚本批准”中完成。 - Omri Spector
这是一个好的解决方案,因为并非所有情况下都有node{}符号。如果您想在从共享库初始化节点之前解析Jenkins参数,则此解决方案将起作用,否则sh('env')将失败。但是在这里不需要@NonCPS。 - Vladislav Kovalyov

15

为什么一切都变得这么复杂?

sh 'env'

做你需要的事情(在*nix下)


2
这需要一个节点块来执行。针对我的用例,我需要处理节点将具有哪些环境,然后根据某些标准启动节点。 - Bill Warner

15

您可以使用 sh/bat 步骤和 readFile 来实现结果:

node {
    sh 'env > env.txt'
    readFile('env.txt').split("\r?\n").each {
        println it
    }
}

不幸的是,env.getEnvironment() 返回的环境变量映射非常有限。


2
sh 'env > env.txt' 运行良好,包括由 shell 进程创建的环境变量。env.getEnvironment() 只显示 Jenkins 设置的环境变量,这是 sh 'env' 技术中所看到的子集。此外,它需要脚本安全批准 method org.jenkinsci.plugins.workflow.support.actions.EnvironmentAction getEnvironmentenv.each { name, value -> println "Name: $name -> Value $value" } 推荐使用 @Renato @Jayan,但只打印 Name: org.jenkinsci.plugins.workflow.cps.EnvActionImpl@45c2d1ee -> Value null - JamesThomasMoon
太好了!能够打印所有环境变量帮助我发现Jenkins 2设置了一个JOB_BASE_NAME变量,其中包含作业名称,但不包括它所在的文件夹。 - Bill Agee
如果有一个在Windows上运行的版本那就太棒了 :) - Bas Hamer
@Bas Hamer,如果要尝试Windows版本,请将“sh”替换为“bat”。 - Sebastien
2
给我一个错误java.lang.UnsupportedOperationException:在CPS转换的闭包上调用公共静态java.lang.Object org.codehaus.groovy.runtime.DefaultGroovyMethods.each(java.lang.Object,groovy.lang.Closure)尚不受支持(JENKINS-26481); 封装在@NonCPS方法中,或使用Java样式循环 - Ben Mathews
这里还有一些更为简洁的选项,另外我会注明这适用于哪些类型的Jenkins流水线,因为这非常重要。 - Wimateeka

14
跨平台列出所有环境变量的方法:
if (isUnix()) {
    sh env
}
else {
    bat set
}

11

这是一个快速的脚本,您可以将其添加为管道作业以列出所有环境变量:

node {
    echo(env.getEnvironment().collect({environmentVariable ->  "${environmentVariable.key} = ${environmentVariable.value}"}).join("\n"))
    echo(System.getenv().collect({environmentVariable ->  "${environmentVariable.key} = ${environmentVariable.value}"}).join("\n"))
}

这将列出系统变量和Jenkins变量。


10

使用纯Groovy解决方案读取全局env变量时,不能打印所有环境变量(例如缺少来自environment块、withEnv上下文以及操作系统中大多数机器特定的变量)。使用shell步骤可以获取更完整的集合,但这需要一个node上下文,这并不总是需要的。

以下是一种解决方案,它使用getContext步骤检索并打印当前上下文的完整环境变量集,包括管道参数。

注意:不适用于Groovy沙盒。但您可以从受信任的共享库中使用它。

def envAll = getContext( hudson.EnvVars )
echo envAll.collect{ k, v -> "$k = $v" }.join('\n')

这是最好的无代理解决方案! - Noam Helmer

8
我将使用蓝海插件,并不喜欢每个环境条目都有自己的块。我希望有一个包含所有行的块。
打印效果很差:
sh 'echo `env`'

印刷质量差:

sh 'env > env.txt'
for (String i : readFile('env.txt').split("\r?\n")) {
    println i
}

打印效果良好:

sh 'env > env.txt'
sh 'cat env.txt'

打印质量好:(如@m jfroehlich所述)

echo sh(script: 'env', returnStdout: true)

6
最简单且最快捷的方法是使用以下网址打印所有环境变量:

http://localhost:8080/env-vars.html/


还有一个有用的链接:https://jenkins.yoururl.com/pipeline-syntax/globals - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接