如何获取使用 Jenkinsfile (groovy) 中的变量执行的 shell 命令的输出?
How do I get the output of a shell command executed using into a variable from Jenkinsfile (groovy)?
我在 Jenkinsfile (Groovy) 上有类似的东西,我想在变量中记录标准输出和退出代码,以便以后使用这些信息。
sh "ls -l"
我该怎么做,尤其是你似乎无法在 Jenkinsfile
中 运行 任何类型的 groovy 代码?
快速回答是这样的:
sh "ls -l > commandResult"
result = readFile('commandResult').trim()
我认为存在能够获取 sh 步骤结果的功能请求,但据我所知,目前没有其他选项。
EDIT2:不太确定从哪个版本开始,但是 sh/bat 步骤现在可以 return std 输出,简单地说:
def output = sh returnStdout: true, script: 'ls -l'
最新版本的管道 sh
步骤允许您执行以下操作;
// Git committer email
GIT_COMMIT_EMAIL = sh (
script: 'git --no-pager show -s --format=\'%ae\'',
returnStdout: true
).trim()
echo "Git committer email: ${GIT_COMMIT_EMAIL}"
另一个功能是 returnStatus
选项。
// Test commit message for flags
BUILD_FULL = sh (
script: "git log -1 --pretty=%B | grep '\[jenkins-full]'",
returnStatus: true
) == 0
echo "Build full flag: ${BUILD_FULL}"
这些选项是根据 this 问题添加的。
sh
命令参见官方 documentation。
对于声明式管道(见评论),您需要将代码包装到 script
步骤:
script {
GIT_COMMIT_EMAIL = sh (
script: 'git --no-pager show -s --format=\'%ae\'',
returnStdout: true
).trim()
echo "Git committer email: ${GIT_COMMIT_EMAIL}"
}
当前 Pipeline 版本原生支持 returnStdout
和 returnStatus
,这使得从 sh
/bat
步骤获取输出或状态成为可能。
一个例子:
def ret = sh(script: 'uname', returnStdout: true)
println ret
一位官员documentation。
这是一个示例案例,我相信这很有意义!
node('master'){
stage('stage1'){
def commit = sh (returnStdout: true, script: '''echo hi
echo bye | grep -o "e"
date
echo lol''').split()
echo "${commit[-1]} "
}
}
如果您想获取标准输出并知道命令是否成功,只需使用 returnStdout
并将其包装在异常处理程序中:
脚本化管道
try {
// Fails with non-zero exit if dir1 does not exist
def dir1 = sh(script:'ls -la dir1', returnStdout:true).trim()
} catch (Exception ex) {
println("Unable to read dir1: ${ex}")
}
输出:
[Pipeline] sh
[Test-Pipeline] Running shell script
+ ls -la dir1
ls: cannot access dir1: No such file or directory
[Pipeline] echo
unable to read dir1: hudson.AbortException: script returned exit code 2
不幸的是 hudson.AbortException 缺少获取该退出状态的任何有用方法,因此如果需要实际值,您需要将其从消息中解析出来(呃!)
与 Javadoc https://javadoc.jenkins-ci.org/hudson/AbortException.html 相反,当捕获到此异常时,构建 不会 失败。当 未 被捕获时它失败了!
更新:
如果您还想要 shell 命令的 STDERR 输出,不幸的是 Jenkins 无法正确支持该常见用例。一张 2017 年票 JENKINS-44930 陷入固执己见的乒乓球状态,同时在解决方案方面没有取得任何进展 - 请考虑给它投赞成票。
至于解决方案现在,可能有几种可能的方法:
a) 将 STDERR 重定向到 STDOUT 2>&1
- 但随后由您将其从主要输出中解析出来,如果命令失败,您将不会获得输出 - 因为您在异常处理程序中。
b) 将 STDERR 重定向到一个临时文件(您之前准备的名称)2>filename
(但记得之后要清理该文件)- 即。主要代码变为:
def stderrfile = 'stderr.out'
try {
def dir1 = sh(script:"ls -la dir1 2>${stderrfile}", returnStdout:true).trim()
} catch (Exception ex) {
def errmsg = readFile(stderrfile)
println("Unable to read dir1: ${ex} - ${errmsg}")
}
c) 换一种方式,改为设置 returnStatus=true
,免除异常处理程序并始终将输出捕获到文件,即:
def outfile = 'stdout.out'
def status = sh(script:"ls -la dir1 >${outfile} 2>&1", returnStatus:true)
def output = readFile(outfile).trim()
if (status == 0) {
// output is directory listing from stdout
} else {
// output is error message from stderr
}
警告:上面的代码是 Unix/Linux-specific - Windows 需要完全不同的 shell 命令。
最简单的方法就是这样使用
my_var=`echo 2`
echo $my_var
输出
: 2
请注意,单引号不是简单的反引号 (`)。
对于那些需要在后续 shell 命令中使用输出而不是 groovy 的人,可以执行类似此示例的操作:
stage('Show Files') {
environment {
MY_FILES = sh(script: 'cd mydir && ls -l', returnStdout: true)
}
steps {
sh '''
echo "$MY_FILES"
'''
}
}
我发现 code maven 上的示例非常有用。
以上方法都行。但是要在代码中使用 var 作为 env 变量,您需要先导出 var。
script{
sh " 'shell command here' > command"
command_var = readFile('command').trim()
sh "export command_var=$command_var"
}
将 shell 命令替换为您选择的命令。现在,如果您使用 python 代码,您只需指定 os.getenv("command_var") 即可 return 先前执行的 shell 命令的输出。
如何读取 groovy 中的 shell 变量/如何将 shell return 值分配给 groovy 变量。
要求:打开文本文件使用 shell 读取行并将值存储在 groovy 中并获取每行的参数。
这里,是分隔符
例如:releaseModule.txt
./APP_TSBASE/app/team/i-home/deployments/ip-cc.war/cs_workflowReport.jar,configurable-wf-report,94,23crb1,artifact
./APP_TSBASE/app/team/i-home/deployments/ip.war/cs_workflowReport.jar,configurable-temppweb-report,394,rvu3crb1,artifact
==========================
此处要获取模块名称第二个参数(configurable-wf-report),不构建第三个参数(94),提交ID 4th(23crb1)
def module = sh(script: """awk -F',' '{ print $2 "," $3 "," $4 }' releaseModules.txt | sort -u """, returnStdout: true).trim()
echo module
List lines = module.split( '\n' ).findAll { !it.startsWith( ',' ) }
def buildid
def Modname
lines.each {
List det1 = it.split(',')
buildid=det1[1].trim()
Modname = det1[0].trim()
tag= det1[2].trim()
echo Modname
echo buildid
echo tag
}
如果您没有一个 sh 命令而是一个 sh 命令块,那么 returnstdout 将不起作用。
我有一个类似的问题,我应用了一些不是干净的方法,但最终它起作用并达到了目的。
解决方案 -
在 shell 块中,回显该值并将其添加到某个文件中。
在 shell 块外和脚本块内,读取此文件,trim 并将其分配给任何 local/params/environment 变量。
例子-
steps {
script {
sh '''
echo $PATH>path.txt
// I am using '>' because I want to create a new file every time to get the newest value of PATH
'''
path = readFile(file: 'path.txt')
path = path.trim() //local groovy variable assignment
//One can assign these values to env and params as below -
env.PATH = path //if you want to assign it to env var
params.PATH = path //if you want to assign it to params var
}
}
我在 Jenkinsfile (Groovy) 上有类似的东西,我想在变量中记录标准输出和退出代码,以便以后使用这些信息。
sh "ls -l"
我该怎么做,尤其是你似乎无法在 Jenkinsfile
中 运行 任何类型的 groovy 代码?
快速回答是这样的:
sh "ls -l > commandResult"
result = readFile('commandResult').trim()
我认为存在能够获取 sh 步骤结果的功能请求,但据我所知,目前没有其他选项。
EDIT2:不太确定从哪个版本开始,但是 sh/bat 步骤现在可以 return std 输出,简单地说:
def output = sh returnStdout: true, script: 'ls -l'
最新版本的管道 sh
步骤允许您执行以下操作;
// Git committer email
GIT_COMMIT_EMAIL = sh (
script: 'git --no-pager show -s --format=\'%ae\'',
returnStdout: true
).trim()
echo "Git committer email: ${GIT_COMMIT_EMAIL}"
另一个功能是 returnStatus
选项。
// Test commit message for flags
BUILD_FULL = sh (
script: "git log -1 --pretty=%B | grep '\[jenkins-full]'",
returnStatus: true
) == 0
echo "Build full flag: ${BUILD_FULL}"
这些选项是根据 this 问题添加的。
sh
命令参见官方 documentation。
对于声明式管道(见评论),您需要将代码包装到 script
步骤:
script {
GIT_COMMIT_EMAIL = sh (
script: 'git --no-pager show -s --format=\'%ae\'',
returnStdout: true
).trim()
echo "Git committer email: ${GIT_COMMIT_EMAIL}"
}
当前 Pipeline 版本原生支持 returnStdout
和 returnStatus
,这使得从 sh
/bat
步骤获取输出或状态成为可能。
一个例子:
def ret = sh(script: 'uname', returnStdout: true)
println ret
一位官员documentation。
这是一个示例案例,我相信这很有意义!
node('master'){
stage('stage1'){
def commit = sh (returnStdout: true, script: '''echo hi
echo bye | grep -o "e"
date
echo lol''').split()
echo "${commit[-1]} "
}
}
如果您想获取标准输出并知道命令是否成功,只需使用 returnStdout
并将其包装在异常处理程序中:
脚本化管道
try {
// Fails with non-zero exit if dir1 does not exist
def dir1 = sh(script:'ls -la dir1', returnStdout:true).trim()
} catch (Exception ex) {
println("Unable to read dir1: ${ex}")
}
输出:
[Pipeline] sh
[Test-Pipeline] Running shell script
+ ls -la dir1
ls: cannot access dir1: No such file or directory
[Pipeline] echo
unable to read dir1: hudson.AbortException: script returned exit code 2
不幸的是 hudson.AbortException 缺少获取该退出状态的任何有用方法,因此如果需要实际值,您需要将其从消息中解析出来(呃!)
与 Javadoc https://javadoc.jenkins-ci.org/hudson/AbortException.html 相反,当捕获到此异常时,构建 不会 失败。当 未 被捕获时它失败了!
更新: 如果您还想要 shell 命令的 STDERR 输出,不幸的是 Jenkins 无法正确支持该常见用例。一张 2017 年票 JENKINS-44930 陷入固执己见的乒乓球状态,同时在解决方案方面没有取得任何进展 - 请考虑给它投赞成票。
至于解决方案现在,可能有几种可能的方法:
a) 将 STDERR 重定向到 STDOUT 2>&1
- 但随后由您将其从主要输出中解析出来,如果命令失败,您将不会获得输出 - 因为您在异常处理程序中。
b) 将 STDERR 重定向到一个临时文件(您之前准备的名称)2>filename
(但记得之后要清理该文件)- 即。主要代码变为:
def stderrfile = 'stderr.out'
try {
def dir1 = sh(script:"ls -la dir1 2>${stderrfile}", returnStdout:true).trim()
} catch (Exception ex) {
def errmsg = readFile(stderrfile)
println("Unable to read dir1: ${ex} - ${errmsg}")
}
c) 换一种方式,改为设置 returnStatus=true
,免除异常处理程序并始终将输出捕获到文件,即:
def outfile = 'stdout.out'
def status = sh(script:"ls -la dir1 >${outfile} 2>&1", returnStatus:true)
def output = readFile(outfile).trim()
if (status == 0) {
// output is directory listing from stdout
} else {
// output is error message from stderr
}
警告:上面的代码是 Unix/Linux-specific - Windows 需要完全不同的 shell 命令。
最简单的方法就是这样使用
my_var=`echo 2`
echo $my_var
输出
: 2
请注意,单引号不是简单的反引号 (`)。
对于那些需要在后续 shell 命令中使用输出而不是 groovy 的人,可以执行类似此示例的操作:
stage('Show Files') {
environment {
MY_FILES = sh(script: 'cd mydir && ls -l', returnStdout: true)
}
steps {
sh '''
echo "$MY_FILES"
'''
}
}
我发现 code maven 上的示例非常有用。
以上方法都行。但是要在代码中使用 var 作为 env 变量,您需要先导出 var。
script{
sh " 'shell command here' > command"
command_var = readFile('command').trim()
sh "export command_var=$command_var"
}
将 shell 命令替换为您选择的命令。现在,如果您使用 python 代码,您只需指定 os.getenv("command_var") 即可 return 先前执行的 shell 命令的输出。
如何读取 groovy 中的 shell 变量/如何将 shell return 值分配给 groovy 变量。
要求:打开文本文件使用 shell 读取行并将值存储在 groovy 中并获取每行的参数。
这里,是分隔符
例如:releaseModule.txt
./APP_TSBASE/app/team/i-home/deployments/ip-cc.war/cs_workflowReport.jar,configurable-wf-report,94,23crb1,artifact
./APP_TSBASE/app/team/i-home/deployments/ip.war/cs_workflowReport.jar,configurable-temppweb-report,394,rvu3crb1,artifact
==========================
此处要获取模块名称第二个参数(configurable-wf-report),不构建第三个参数(94),提交ID 4th(23crb1)
def module = sh(script: """awk -F',' '{ print $2 "," $3 "," $4 }' releaseModules.txt | sort -u """, returnStdout: true).trim()
echo module
List lines = module.split( '\n' ).findAll { !it.startsWith( ',' ) }
def buildid
def Modname
lines.each {
List det1 = it.split(',')
buildid=det1[1].trim()
Modname = det1[0].trim()
tag= det1[2].trim()
echo Modname
echo buildid
echo tag
}
如果您没有一个 sh 命令而是一个 sh 命令块,那么 returnstdout 将不起作用。
我有一个类似的问题,我应用了一些不是干净的方法,但最终它起作用并达到了目的。
解决方案 - 在 shell 块中,回显该值并将其添加到某个文件中。 在 shell 块外和脚本块内,读取此文件,trim 并将其分配给任何 local/params/environment 变量。
例子-
steps {
script {
sh '''
echo $PATH>path.txt
// I am using '>' because I want to create a new file every time to get the newest value of PATH
'''
path = readFile(file: 'path.txt')
path = path.trim() //local groovy variable assignment
//One can assign these values to env and params as below -
env.PATH = path //if you want to assign it to env var
params.PATH = path //if you want to assign it to params var
}
}