如何使用Jenkinsfile(groovy)中的变量执行shell命令的输出?

sor*_*rin 178 groovy jenkins-workflow jenkins-pipeline jenkinsfile

我在Jenkinsfile(Groovy)上有这样的东西,我想在变量中记录stdout和退出代码,以便稍后使用这些信息.

sh "ls -l"
Run Code Online (Sandbox Code Playgroud)

我怎么能这样做,特别是因为你似乎无法在里面运行任何类型的groovy代码Jenkinsfile

G. *_*ans 320

最新版本的管道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}"
Run Code Online (Sandbox Code Playgroud)

另一个功能是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}"
Run Code Online (Sandbox Code Playgroud)

基于问题添加的这些选项.

请参阅该命令的官方文档sh.

  • 似乎这只适用于`script`步骤块.https://jenkins.io/doc/book/pipeline/syntax/#declarative-steps (16认同)
  • 看起来现在已经记录了 - > https://jenkins.io/doc/pipeline/steps/workflow-durable-task-step/#code-sh-code-shell-script (10认同)
  • 当我使用声明性jenkinsfile语法时,这不起作用,错误信息是:```WorkflowScript:97:预期步骤@第97行,第17列.`` (6认同)
  • 在官方文档链接 https://jenkins.io/doc/pipeline/steps/workflow-durable-task-step/#sh-shell-script 中,我没有看到任何对 sh 步骤或其选项(如 returnStdout)的引用。它仍然是文档的正确链接吗? (4认同)

veh*_*mar 40

快速回答是这样的:

sh "ls -l > commandResult"
result = readFile('commandResult').trim()
Run Code Online (Sandbox Code Playgroud)

我认为有一个功能请求能够得到sh步的结果,但据我所知,目前没有其他选择.

编辑:JENKINS-26133

编辑2:不太确定,因为什么版本,但sh/bat步骤现在可以返回标准输出,简单地说:

def output = sh returnStdout: true, script: 'ls -l'
Run Code Online (Sandbox Code Playgroud)

  • 另外仅供参考,bat 步骤会回显正在运行的命令,因此您需要使用 @ 启动 bat 命令才能获取输出(例如“@dir”)。 (2认同)

luk*_*a5z 38

当前管道版本本身支持returnStdoutreturnStatus,这使得它能够得到输出或状态sh/ bat步骤.

一个例子:

def ret = sh(script: 'uname', returnStdout: true)
println ret
Run Code Online (Sandbox Code Playgroud)

官方文件.

  • 这些语句将包含在“script { }”步骤中。 (5认同)

Bib*_*ree 11

这是一个示例案例,我相信这是有道理的!

node('master'){
    stage('stage1'){
    def commit = sh (returnStdout: true, script: '''echo hi
    echo bye | grep -o "e"
    date
    echo lol''').split()


    echo "${commit[-1]} "

    }
}
Run Code Online (Sandbox Code Playgroud)


Ed *_*all 11

如果要获取标准输出并知道命令是否成功,只需使用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}")
}
Run Code Online (Sandbox Code Playgroud)

输出

[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
Run Code Online (Sandbox Code Playgroud)

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

与Javadoc https://javadoc.jenkins-ci.org/hudson/AbortException.html相反,捕获到此异常时构建不会失败。如果没有捕获,它将失败!

更新: 如果您还希望从shell命令输出STDERR,则可能有两种可能的方法:

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}")
}
Run Code Online (Sandbox Code Playgroud)

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
}
Run Code Online (Sandbox Code Playgroud)

注意:上面的代码特定于Unix / Linux-Windows需要完全不同的shell命令。

  • 我不明白这怎么行得通。在我的测试中,输出文本从未被分配,这是可以预料的。shell 步骤抛出的异常阻止分配返回值 (2认同)
  • 不幸的是,returnStatus 和 returnStdout 不能同时工作。这是门票。请投票:https://issues.jenkins-ci.org/browse/JENKINS-44930。 (2认同)

Nag*_*gev 7

对于那些需要在后续 shell 命令中使用输出而不是 groovy 的人,可以执行以下示例:

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

我发现代码 maven上的示例非常有用。