如何/何时执行Shell将构建标记为Jenkins中的失败?

时间:2014-04-02 14:25:24

标签: shell unix jenkins build hudson

我在寻找这个答案时发现的恐怖故事......

好的,我有一个.sh脚本,几乎可以完成Jenkins应该做的所有事情:

  • 检查SVN的来源
  • 构建项目
  • 部署项目
  • 自行清理

所以在詹金斯,我只需要建立'通过在Execute Shell命令中运行脚本来实现该项目。  脚本已运行(源代码已下载,项目已构建/部署)但随后它将构建标记为失败: 构建步骤'执行shell'标记为失败 即使脚本成功运行!我尝试用以下方法关闭脚本:

  • 退出0(仍将其标记为失败)
  • 退出1(将其标记为失败,如预期)
  • 根本没有退出命令(将其标记为失败)

Execute Shell何时,如何以及为何将我的构建标记为失败?

6 个答案:

答案 0 :(得分:121)

首先,将鼠标悬停在下方的灰色区域上。不是答案的一部分,但绝对必须说:

  

如果你有一个单独执行“checkout,build,deploy”的shell脚本,那你为什么要使用Jenkins?你已经了解了詹金斯的所有功能,使它成为现实。 你可能还有一个cron或一个SVN post-commit钩子直接调用脚本。 Jenkins执行SVN结账本身至关重要。它允许仅在有更改时触发构建(或者如果您愿意,可以在计时器或手动上触发)。它跟踪构建之间的变化。它显示了这些更改,因此您可以看到哪个版本适用于哪组更改。当它们的更改导致构建成功或失败时,它会通过电子邮件发送提交者(同样,根据您的喜好进行配置)。当他们的修复修复了失败的构建时,它将通过电子邮件发送提交者。而且越来越多。詹金斯归档这些文物也使得它们可以在每个版本中直接使用Jenkins。虽然不如SVN结账那么重要,但这再次成为Jenkins的重要组成部分。与部署相同。除非您拥有单一环境,否则部署通常会发生在多个环境中。通过使用Promotions,Jenkins可以跟踪特定构建(具有特定的SVN更改集)的环境。你已经完成了这一切。这听起来像你被告知“你必须使用詹金斯”,但你真的不想这样做,而你这样做只是为了让你的老板脱离你的背,只是勾选“是的,我用过詹金斯”

简短的回答是:Jenkin的执行Shell 构建步骤的最后命令的退出代码决定了构建步骤<的成功/失败/ strong>即可。 0 - 成功,anything else - 失败。 请注意,这是确定构建步骤的成功/失败,而不是整个作业运行。整个作业运行的成功/失败可能会受到多个构建步骤以及构建后操作和插件的影响。

您已经提到了Build step 'Execute shell' marked build as failure,因此我们只关注单个构建步骤。如果您的执行shell 构建步骤只有一行调用您的shell脚本,那么shell脚本的退出代码将确定构建步骤的成功/失败。如果您的shell脚本执行后有更多行 ,那么请仔细查看它们,因为它们可能会导致失败。

最后,请阅读 Jenkins Build Script exits after Google Test execution 。它与您的问题没有直接关系,但请注意关于Jenkins启动执行Shell 构建步骤的部分,作为带有 /bin/sh -xe

的shell脚本

-e表示shell脚本将退出失败,即使只有1个命令失败,甚至如果您对该命令执行错误检查(因为脚本在进入错误检查之前退出)。这与正常执行shell脚本相反,shell脚本通常会打印失败命令的错误消息(或将其重定向为null并通过其他方式处理它),然后继续。

要避免这种情况,请将set +e添加到shell脚本的顶部。

既然你说你的脚本完成了它应该做的所有事情,那么失败的命令可能就在脚本末尾的某个地方。也许是最后的回声?或者在某处复制文物?没有看到完整的控制台输出,我们只是在猜测。

请发布作业运行的控制台输出,最好是shell脚本本身,然后我们可以确切地告诉您哪条线路出现故障。

答案 1 :(得分:80)

简单而简短的回答是

请在“执行shell”构建步骤中添加以下行。

#!/bin/sh

现在让我向您解释为什么我们需要“Execute Shell”构建作业的这一行。

默认情况下,Jenkins使用/bin/sh -xe,这意味着-x将打印每个命令。另一个选项-e,这会导致shell在任何命令退出时立即停止运行脚本非零(当任何命令失败时)退出代码。

因此,添加#!/bin/sh将允许您执行无选项。

答案 2 :(得分:2)

简单明了:

如果Jenkins看到构建步骤(也是一个脚本)以非零代码退出,则构建标记为红色球(=失败)。

为什么会发生这种情况取决于您的构建脚本。

我从另一个观点写了类似的东西,但也许它有助于阅读它: Why does Jenkins think my build succeeded?

答案 3 :(得分:2)

在我看来,关闭shell的-e选项是一个非常糟糕的主意。最终,由于磁盘空间不足或网络错误等瞬态条件,脚本中的一个命令将失败。没有-e詹金斯没有注意到并将继续愉快地继续。如果您已经设置Jenkins进行部署,则可能会导致错误的代码被推送并关闭您的网站。

如果脚本中有一行可能出现故障,例如grep或find,那么只需将|| true添加到该行的末尾即可。这可以确保该行始终返回成功。

如果您需要使用该退出代码,可以将命令提升到if语句中:

grep foo bar; if [ $? == 0 ]; then ...    -->   if grep foo bar; then ...

或者您可以在||子句中捕获返回码:

grep foo bar || ret=$?

答案 4 :(得分:0)

因此,添加#!/bin/sh将允许您执行无选项。

它还帮助我解决了我在Linux slave上从Jenkins master执行bash脚本的问题。只需将#!/bin/bash添加到我的实际脚本之上&#34;执行Shell&#34;阻止它修复了我的问题,否则它正在执行windows git提供的bash shell版本给出错误。

答案 5 :(得分:0)

在詹金斯版中。 1.635,不可能显示这样的本地环境变量:

$ BUILD_NUMBER或$ {BUILD_NUMBER}

在这种情况下,您必须将其设置在另一个变量中。

设置BUILDNO = $ BUILD_NUMBER $ BUILDNO