Execute Shell如何/何时在Jenkins中将构build标记为失败?

我在寻找这个答案时find的恐怖故事…

好的,我有一个.sh脚本,几乎所有的Jenkins都应该这样做:

  • 检查SVN的来源
  • build立项目
  • 部署项目
  • 自己清理

所以在Jenkins中,我只需要通过在Execute Shell命令中运行脚本来“build立”项目。 脚本运行(下载源代码,项目build立/部署),但是它将构build标记为失败:构build步骤'执行shell'标记构build失败即使脚本已成功运行! 我尝试closures脚本:

  • 退出0(仍然标志为失败)
  • 出口1(如预期的那样将其标记为失败)
  • 根本没有退出命令(标记为失败)

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

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

如果你有一个shell脚本自己完成“checkout,build,deploy”,那么你为什么使用Jenkins呢? jenkins的所有function都是完美的。 你可能有一个cron或SVN后提交挂钩直接调用脚本 。 Jenkins执行SVN结帐本身至关重要。 它允许构build只有在发生变化时(或定时器,或手动,如果你喜欢)触发。 它跟踪构build之间的变化。 它显示了这些变化,所以你可以看到哪个版本是为了哪一组更改。 它发送电子邮件提交者,当他们的变化造成成功或失败的构build(再次,如你所愿configuration)。 它会在修复程序修复失败的构build时向发送者发送电子邮件。 而且越来越多。 jenkins存档的文物也使得他们每个构build,直接closuresjenkins。 虽然没有SVN结帐那么重要,但这又是使Jenkins成为一个不可或缺的部分。 和部署一样。 除非你有单一的环境,否则部署通常发生在多个环境中。 Jenkins可以通过使用Promotions来跟踪特定版本(具有特定的SVN更改集)在哪个环境中部署。 你是前面所有这一切。 这听起来像你被告知“你必须使用jenkins”,但你不是真的想要,而你只是为了让你的老板从背后,只是为了勾选“是的,我用jenkins”

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

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

最后,请阅读这里Jenkins Build Script在Google Test执行后退出 。 它与你的问题没有直接关系,但是请注意,关于Jenkins启动Execute Shell构build步骤的一部分,作为一个带有/bin/sh -xe的shell脚本

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

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

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

请发布作业运行的控制台输出,最好是shell脚本本身,然后我们可以告诉你到底哪一行是失败的。

简单和简短的回答你的问题是

请在“Execute shell”构build步骤中添加以下行。

 #!/bin/sh 

现在让我解释一下为什么我们需要这行“Execute Shell”构build作业的原因。

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

所以通过添加#!/bin/sh将允许你执行没有选项。

干净利落:

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

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

我从另一个angular度写了一些类似的东西,但也许这将有助于阅读: Jenkins为什么认为我的构build成功了?

在我看来,closuresshell的-e选项是一个非常糟糕的主意。 最终,脚本中的某个命令将因磁盘空间不足或networking错误等瞬态情况而失败。 没有-ejenkins不会注意,并会继续愉快地。 如果您已经设置了Jenkins来进行部署,那么可能会导致错误的代码被推入,导致您的网站无法正常运行。

如果你的脚本中有一行会出现错误,比如grep或者find,那么只需要添加|| true || true到那条线的尽头。 这确保这条线总是会返回成功。

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

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

或者你可以在你的||捕获返回码 条款:

 grep foo bar || ret=$? 

所以通过添加#!/bin/sh将允许你执行没有选项。

它还帮助我解决了一个问题,即在我的Linux从服务器上执行Jenkins master的bash脚本。 通过在我的实际脚本上面加上#!/bin/bash ,它就解决了我的问题,否则它会执行windows git提供的bash shell版本,从而导致错误。