[英]How to get environment variable in Jenkins Groovy script console?
在“全局屬性”中的 Jenkins 配置( http://JenkinsURL/configure )中,我定義了一些“環境變量”。
如何在 Groovy Script 控制台 ( http://JenkinsURL/script ) 中訪問它們?
我試圖找到合適的解決方案(例如在: Access to build environment variables from a groovy script in a Jenkins build step (Windows) 中提到的解決方案),但似乎它們都不適合我。
我試過例如:
System.getenv("myVar")
和
manager.build.getEnvironment(listener).get('myVar') //no manager error
和
import jenkins.model.Jenkins
Jenkins.instance.getProperty('myVar') //No signature of method: hudson.model.Hudson.getProperty() is applicable for argument types: (java.lang.String)
和
import jenkins.model.Jenkins
Jenkins.instance.ParameterValue("DEV_local")
您可以像這樣獲得全局屬性:
import jenkins.model.Jenkins
def envVars = Jenkins.instance.getGlobalNodeProperties()[0].getEnvVars()
println envVars['myVar']
我參考了下面的鏈接,關於如何以編程方式設置全局屬性。 https://groups.google.com/forum/#!topic/jenkinsci-users/KgCGuDmED1Q
它並不像您想象的那么簡單,就像 Jenkins 中的一切一樣。 它似乎沒有公開一個簡單的 API 來獲取當前執行上下文的最終有效環境,至少沒有公開到腳本控制台。
這是您可以直接使用的打包版本,或者您可以稍作修改以捆綁到管道全局庫中的vars/
類中。
import jenkins.model.Jenkins
import hudson.model.Node
import hudson.slaves.EnvironmentVariablesNodeProperty
import hudson.EnvVars
EnvVars getCombinedNodeEnvironment(Node node) {
/*
* Start with env-vars defined by the shell the JVM
* was started from and env-vars set as system properties.
*/
def combined = new EnvVars(node.toComputer().getEnvironment())
/*
* Apply environment variables from jenkins global settings
* ("Manage Jenkins" -> "Configure System" -> "Global Properties"
* -> "Environment Variables")
*/
combined.overrideExpandingAll(Jenkins.instance.
getGlobalNodeProperties().
get(EnvironmentVariablesNodeProperty).
getEnvVars() ?: new EnvVars())
/*
* Apply environment variables from node specific settings
* ("Manage Jenkins" -> "Manage Nodes and Clouds"
* -> {nodename} -> "Configure" -> "Node Properties"
* -> "Environment Variables")
*/
combined.overrideExpandingAll((node.
getNodeProperty(EnvironmentVariablesNodeProperty)?.
getEnvVars()) ?: new EnvVars())
/*
* Important: This environment map will NOT contain job-level,
* or run-level properties, nor anything set via build steps etc.
*/
return combined
}
EnvVars getCombinedNodeEnvironment(String nodename) {
if (nodename == 'master' || !nodename)
return getCombinedNodeEnvironment(Jenkins.instance)
else
return getCombinedNodeEnvironment(Jenkins.instance.getNode(nodename))
}
用法:
getCombinedNodeEnvironment('somenode').expand('$JENKINS_HOME/$USER/$SOME_NODE_VARIABLE')
getCombinedNodeEnvironment('').SOME_ENV_VAR_ON_MASTER
相關類:
hudson.model.Node
jenkins.model.Jenkins
hudson.EnvVars
hudson.slaves.EnvironmentVariablesNodeProperty
hudson.util.DescribableList
arasio 的回答是一個好的開始,但假設 envvars 屬性將位於全局屬性的索引 0 是不正確的。 該方法還會忽略在特定節點上本地設置的環境變量。
至少它應該讀
jenkins.instance.Jenkins.instance.
getGlobalNodeProperties().
get(hudson.slaves.EnvironmentVariablesNodeProperty).
getEnvVars()
即在DescribableList
結果中按類查找屬性,而不是假設索引。
但是,這只會讓您從全局 jenkins 配置中的“環境變量”列表中獲取環境變量- 它不會顯示系統環境變量,也不會顯示特定於節點的環境變量。
繼續閱讀。
如果您使用的是 Groovy 管道,大多數時候您可以只使用env
“變量” (請參閱管道幫助中的“全局變量引用”),它將統一環境公開為屬性。 如上所述,這不能直接從腳本控制台工作,但在其余時間它是做事的合適方式。
您還可以在流水線腳本中使用env.getEnvironment()
來獲得統一的EnvVars
實例,該實例用於字符串中 env-vars 的占位符替換,例如env.getEnvironment().expand('${FOO} $BAR')
。 (您需要為此獲得腳本安全權限,但最好將其放在全局庫vars/
的幫助程序中)。
大多數時候這已經足夠了。
我只是深入研究環境結構的細節,因為我需要擴展包含環境變量的字符串,因為它們將在不同的節點上擴展。 這不是一個常見的用例。
這是最后的秘訣,但我們是如何到達那里的,不同的環境變量集從何而來,為什么?
對於下面的代碼示例,假設這個共同的前奏,主要是為了節省每個示例中的重復。
/* Jenkins uses '' for the master node */
nodenames = ['', 'some-other-node-name']
/* Imports used in various examples */
import jenkins.model.Jenkins
import hudson.slaves.EnvironmentVariablesNodeProperty
import hudson.EnvVars
nodes = nodenames.collect { nodename ->
(!nodename || nodename == 'master') ?
Jenkins.instance : Jenkins.instance.getNode(nodename)
import static groovy.json.JsonOutput.toJson
import static groovy.json.JsonOutput.prettyPrint
def eachNode(Closure c) {
nodes.collectEntries { node -> [node.nodeName, c(node, node.nodeName) ] }
def fmtEnv(desc,m) {
print "\n\n${desc}\n----\n" + m.collect { k, v -> "${k?:'master'}:\n\t${trimKeys(v)}" }.join('\n')
}
def trimKeys(l) {
if (l == null)
return l
if (l in Map)
l = l.keySet()
l = l - ['_', 'OLDPWD', 'PWD', 'SSH_CLIENT', 'JAVA_HOME', 'LANG', 'LOGNAME', 'MAIL', 'MANPATH', 'S_COLORS', 'SHLVL', 'XDG_RUNTIME_DIR', 'XDG_SESSION_ID']
l.sort()
}
nodes
現在包含jenkins.model.Jenkins
主節點和一個hudson.model.Node
工作節點。
eachNode
生成節點名稱到環境變量鍵的縮寫列表的映射,只是為了使示例更簡潔易讀。 不要在你的代碼中使用它。
為了幫助闡明這些示例的結果,我在 node1 的節點設置中的“管理 Jenkins”->“管理節點和雲”-> [節點名稱]-> 配置-> 環境變量下配置了NODE1_SPECIFIC_ENVVAR
。
在同一個地方的主節點條目上,我已經配置了MASTER_SPECIFIC_ENVVAR
在“管理詹金斯”->“配置系統”->“全局屬性”->“環境變量”中,我添加了“ALL_NODES_ENVVAR”。
我沒有費心在 JVM 級別為節點和主節點設置自定義 env-vars。
現在,讓我們以不同的方式探索環境。
在主機上, System.getenv()
僅顯示 JVM 啟動時設置的環境變量或作為系統屬性:
fmtEnv('System.getenv()', ['': System.getenv()])
/*
master:
[HOME, JENKINS_HOME, PATH, SHELL, USER]
*/
所以沒有配置每個節點,全局在 jenkins 本身或每個作業。
Jenkins 在其 API 中公開在每個節點上設置的基本環境變量。 我認為這與System.getEnv()
在目標節點 JVM 上執行時返回的結果相同:
fmtEnv('toComputer.getEnvironment()', eachNode() {
node, name -> node.toComputer().getEnvironment()
})
/*
master:
[HOME, JENKINS_HOME, PATH, SHELL, USER]
ci-node-qa-fsn1-01:
[HOME, PATH, SHELL, SSH_CONNECTION, USER]
*/
請注意 Jenkins 中沒有設置全局或節點特定的 env-vars。
fmtEnv('master getGlobalNodeProperties', ['':
Jenkins.instance.
getGlobalNodeProperties().
get(EnvironmentVariablesNodeProperty).
getEnvVars()
])
/*
master getGlobalNodeProperties
----
master:
[ALL_NODES_ENVVAR]
*/
所以在這里我們只能看到全局配置的環境屬性,而不是特定於節點的屬性、系統屬性或主機環境變量。
fmtEnv('node getNodeProperty', eachNode() {
node, name -> node.getNodeProperty(EnvironmentVariablesNodeProperty)?.getEnvVars()
})
/*
master:
[MASTER_SPECIFIC_ENVVAR]
ci-node-qa-fsn1-01:
[NODE1_SPECIFIC_ENVVAR]
*/
在這里,我們在“管理節點”中看到每個節點下配置的屬性,但不是主機環境變量、系統屬性變量、標准 jenkins 作業變量或在 jenkins 全局配置中配置的變量。
重要提示:如果節點上沒有配置自定義環境變量, getNodeProperty(EnvironmentVariablesNodeProperty)
將返回null
,因此您必須處理它。
上面顯示了如何為腳本控制台上有意義的環境變量的主要來源獲取EnvVars
實例。
運行作業時還有其他來源,我在這里不考慮,例如作業屬性(EnvInject 插件)、添加到所有作業的自動 env-vars、 withEnvironment
步驟、由 SCM 插件注入的變量等。但是它們對腳本控制台任務沒有意義。
那么我們如何獲得一個統一的環境呢?
首先,收集環境中每個相關部分的EnvVars
:
def node_base_env = node.toComputer().getEnvironment()
def global_env_properties = Jenkins.instance.
getGlobalNodeProperties().
get(EnvironmentVariablesNodeProperty).
getEnvVars()
def node_env_properties = node.getNodeProperty(EnvironmentVariablesNodeProperty)?.getEnvVars() ?: new EnvVars()
def merged = new EnvVars(node_base_env)
merged.overrideExpandingAll(global_env_properties)
merged.overrideExpandingAll(node_env_properties)
merged
/*
master:
[ALL_NODES_ENVVAR, HOME, JENKINS_HOME, MASTER_SPECIFIC_ENVVAR, PATH, SHELL, USER]
ci-node-qa-fsn1-01:
[ALL_NODES_ENVVAR, HOME, NODE1_SPECIFIC_ENVVAR, PATH, SHELL, SSH_CONNECTION, USER]
*/
我很確定這會產生正確的結果。 我沒有詳細測試擴展處理、優先級覆蓋順序或擴展順序。
(注意:我刪除了另一個使用EnvironmentExpander
示例)。
您可以使用System
來獲取環境變量。
def env = System.getenv()
println(env['JENKINS_HOME'])
(另請參閱http://@myJenkHostname@/env-vars.html (其中@myJenkHostname@
是您的 Jenkins 主機名)以獲取內置環境變量的列表。)
由於“安全”問題,這些答案都不適合我。 而只是使用環境變量的名稱,例如您可以使用的環境變量 PATH:
final path = PATH
你也可以使用
final path = env.PATH
很驚訝它是如此簡單,但它是......
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.