在流水线中,是否有可能从sh DSL命令捕获标准输出(stdout)?

116
例如:
var output=sh "echo foo";
echo "output=$output";

我将得到:

output=0

显然,我得到的是退出代码而不是标准输出。是否可能将标准输出捕获到管道变量中,以便我可以得到以下结果:output=foo

7个回答

268

现在sh 步骤 支持通过提供参数 returnStdout 返回 stdout

// These should all be performed at the point where you've
// checked out your sources on the slave. A 'git' executable
// must be available.
// Most typical, if you're not cloning into a sub directory
gitCommit = sh(returnStdout: true, script: 'git rev-parse HEAD').trim()
// short SHA, possibly better for chat notifications, etc.
shortCommit = gitCommit.take(6)

请查看此示例


14
请将英语翻译成中文。仅返回已翻译的文本:请注意此答案的 .trim() 部分,否则您可能会在行末得到一个换行符。 - Will Munn
2
在编程中,将“--short”附加到“rev-parse”可以直接获取短哈希。 - Leon
2
不确定是什么导致了失败,但我不得不将输出转换为字符串,就像这样 gitCommit = sh(returnStdout: true, script: 'git rev-parse HEAD').toString().trim() - Balkrishna
1
嗨,'.take(6)'代表什么? - Vano
2
@Vano 指的是 Groovy 的 take() 方法,该方法将在此情况下获取前6个字符。http://docs.groovy-lang.org/docs/groovy-2.3.2/html/api/org/codehaus/groovy/runtime/StringGroovyMethods.html#take(java.lang.CharSequence,%20int) - ahillman3
在我的情况下,当我在某些其他函数中使用myvar.take()时,我会收到java.lang.NullPointerException:Cannot invoke method trim() on null object,而它只在简单的sh 'echo'+myvar.take()中有效。 - holms

49

注意:链接的Jenkins问题已经得到解决。

JENKINS-26133所述,以前无法将shell输出作为变量获取。一个解决方法是使用临时文件进行写入和读取操作。因此,您的示例应该如下所示:

sh "echo foo > result";
def output=readFile('result').trim()
echo "output=$output";

22
对于新手,请查看下面的答案https://dev59.com/EFoV5IYBdhLWcg3wPcxv#38912813,这是通过传递到`sh`步骤的新`returnStdout`参数更加容易实现的。 - Baptiste Mathus
2
“不可能将shell输出作为变量获取” - 这并不是真的。这是一个hack,正确的答案是returnStdout。 - Graham
4
只有当你需要获取 shell 命令的 stdoutexit status 时,这才是一个好的答案。其他情况下,请使用 returnStdout 参数。 - Simon Forsberg

5

试试这个:

def get_git_sha(git_dir='') {
    dir(git_dir) {
        return sh(returnStdout: true, script: 'git rev-parse HEAD').trim()
    }
}

node(BUILD_NODE) {
    ...
    repo_SHA = get_git_sha('src/FooBar.git')
    echo repo_SHA
    ...
}

测试环境:

  • Jenkins 版本号 2.19.1
  • Pipeline 版本号 2.4

5
你可以尝试使用这些函数来捕获标准错误、标准输出和返回代码。
def runShell(String command){
    def responseCode = sh returnStatus: true, script: "${command} &> tmp.txt" 
    def output =  readFile(file: "tmp.txt")

    if (responseCode != 0){
      println "[ERROR] ${output}"
      throw new Exception("${output}")
    }else{
      return "${output}"
    }
}

注意:

&>name means 1>name 2>name -- redirect stdout and stderr to the file name

4

我曾经遇到相同的问题,试了几乎所有方法,后来发现我一直在错误的块中尝试。我一直在步骤块中尝试,但实际上需要在环境块中进行。

        stage('Release') {
                    environment {
                            my_var = sh(script: "/bin/bash ${assign_version} || ls ", , returnStdout: true).trim()
                                }
                    steps {                                 
                            println my_var
                            }
                }

1
一句简短的版本是:
echo sh(script: 'ls -al', returnStdout: true).result

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接