我如何从Jenkinsfile (groovy)得到一个shell命令的输出?

我在Jenkinsfile (Groovy)上有类似的东西,我想在一个变量中记录标准输出和退出码,以便以后使用这些信息。

sh "ls -l"

我怎么能做到这一点,特别是因为似乎你不能真正运行任何类型的Jenkinsfile中的groovy代码?

540688 次浏览

简单的回答是:

sh "ls -l > commandResult"
result = readFile('commandResult').trim()

我认为存在一个特性请求能够得到sh步骤的结果,但据我所知,目前没有其他选择。

编辑:詹金斯- 26133

EDIT2:不太确定从哪个版本开始,但是sh/bat步骤现在可以返回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}"

这些选项是根据问题添加的。

有关sh命令,请参阅官方文档

对于声明式管道(见注释),你需要将代码包装到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版本本机支持returnStdoutreturnStatus,这使得从sh/bat步骤获得输出或状态成为可能。

一个例子:

def ret = sh(script: 'uname', returnStdout: true)
println ret

一个官方的文档

这是一个例子,我相信这是有意义的!

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

不幸的是,哈德逊。AbortException缺少任何用于获取退出状态的有用方法,因此如果需要实际值,则需要从消息中解析它(哎呀!)

与Javadoc https://javadoc.jenkins-ci.org/hudson/AbortException.html相反,当捕获此异常时,构建是失败。当被捕获时,它会失败!

< >强更新: 如果您还想从shell命令得到STDERR输出,不幸的是Jenkins不能正确地支持这种常见的用例。一张2017年的票詹金斯- 44930陷入了固执己见的乒乓状态,同时在解决方案方面没有取得任何进展-请考虑添加你的upvote给它

对于解决方案现在,可能有几个可能的方法:

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特定的- Windows需要完全不同的shell命令。

最简单的方法就是用这种方法

< p > <代码> my_var = '回声2》 echo $ my_var 输出 : 2 < / p >

注意不是简单的单引号是反引号(')。

对于那些需要在后续shell命令中使用输出的人,而不是groovy,可以像这样做:

    stage('Show Files') {
environment {
MY_FILES = sh(script: 'cd mydir && ls -l', returnStdout: true)
}
steps {
sh '''
echo "$MY_FILES"
'''
}
}

我发现代码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"),它将返回之前执行的shell命令的输出。

如何读取groovy中的shell变量/如何将shell返回值分配给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

========================

这里想要获得模块名称的第2个参数(configuration -wf-report),不构建第3个参数(94),提交id第4 (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将不起作用。

我有一个类似的问题,我应用了一些东西,这不是一个干净的方式,但最终它工作了,并达到了目的。

——< p >解决方案 在shell块中,回显该值并将其添加到某个文件中。 在shell块之外和脚本块内部,读取这个文件,修剪它并将其分配给任何本地/params/环境变量

的例子,

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




}
}