Jenkins Pipeline脚本中的returnStatus值为什么与shell中检查的状态不匹配

41次阅读
没有评论

问题描述

在编写Jenkins Pipeline脚本时遇到了一个问题。他的脚本中使用了sh命令执行一些shell命令,并且设置了returnStatus参数来获取命令的返回状态。然而,他发现在执行cd命令失败时,返回的状态码为2,而在bash中,cd到不存在的目录时返回的状态码应该是1。用户想知道为什么会出现这种情况。

解决方案

请注意以下操作注意版本差异及修改前做好备份。

问题分析

首先需要注意的是,如果没有提供shebang(即脚本的解释器),实际上将使用的解释器是”sh”,而不是”bash”。
查看Jenkins的源代码,可以发现当调用sh命令时,Jenkins并不直接返回子shell的退出码,而是监视一个名为”jenkins-result.txt”的文件的变化,并将其内容作为退出状态。实际上,当调用”sh”命令时,Jenkins会将脚本代码包装在一段相当大的样板代码中。这段代码的作用是监视文件的变化并将其内容作为退出状态。

解决方案

根据上述分析,可以得出以下结论:
1. Jenkins在执行sh命令时会将脚本代码包装在一段样板代码中,这段代码会影响返回的退出状态。
2. 由于使用的解释器是”sh”,而不是”bash”,因此返回的状态码可能与bash中的不同。

为了获取真正的命令返回状态,可以尝试以下方法:
1. 使用returnStdout参数获取命令的标准输出,并根据输出内容判断命令是否执行成功。
2. 使用其他方法或工具来执行命令,并获取命令的返回状态。

示例

以下是一个示例脚本,可以获取命令的返回状态:

node {
    stage("hello") {
        def var = "val"
        echo "${var}"
        def stdout = sh(script: 'pwd', returnStdout: true).trim()
        echo "${stdout}"
        def ret_status = sh(script: 'cd subdir', returnStatus: true)
        echo "${ret_status}"
        if (ret_status == 0) {
            echo "Command executed successfully"
        } else {
            echo "Command failed"
        }
    }
}

在上面的示例中,我们使用returnStatus参数获取命令的返回状态,并根据返回状态判断命令是否执行成功。

请注意,这个问题也展示了Jenkins和Groovy的一些复杂性。在使用Jenkins Pipeline时,需要仔细考虑脚本的执行环境和返回状态的获取方式,以确保正确获取命令的返回状态。

评论:
1. 我同意你的观点,这种方式确实存在很多错误的可能性。这就引出了另一个问题:是否有其他方法可以捕获命令的真实状态码?我还在努力理解DevOps的思维方式…所以我也想知道:sh(..., returnStatus:true)表示什么?我是说 – 你的答案很清楚:它是样板代码的返回码…但是为什么DevOps工程师会想要获取那个值,而不是他实际命令的返回状态呢?(后者似乎更自然)2. 这个问题和答案很好地说明了Jenkins+Groovy的复杂性(在我看来)。

参考资料

正文完