问题描述
在编写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的复杂性(在我看来)。
参考资料