簡體   English   中英

如何在 Jenkins Groovy 腳本控制台中獲取環境變量?

[英]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

相關類:

現有答案的問題

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。

對環境的不同看法

現在,讓我們以不同的方式探索環境。

JVM 級環境變量(主)

在主機上, 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.

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