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


112

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

好的,我有一个.sh脚本,它几乎完成了詹金斯应该做的所有事情:

  • 从SVN检出源
  • 建立项目
  • 部署项目
  • 自己清洗

因此,在Jenkins中,我只需要通过在Execute Shell命令中运行脚本来“构建”项目。脚本已运行(下载了源代码,项目正在构建/部署中),但随后将构建标记为失败:生成步骤'Execute shell'将生成标记为失败,即使脚本已成功运行!我尝试用以下命令关闭脚本:

  • 退出0(仍将其标记为失败)
  • 出口1(按预期将其标记为失败)
  • 完全没有退出命令(将其标记为失败)

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

Answers:


130

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

如果您有一个shell脚本自己单独执行“签出,构建,部署”,那么为什么要使用Jenkins?您将继承詹金斯的所有功能,使其成为现实。您可能还有cron或SVN提交后钩子,请直接调用脚本。詹金斯(Jenkins)执行SVN结帐本身至关重要。它允许仅在有更改时(或按计时器或手动(如果您愿意))触发构建。它跟踪构建之间的更改。它显示了这些更改,因此您可以查看哪个构建适用于哪个更改集。当提交者的更改导致构建成功或失败时,它将通过电子邮件发送给提交者(同样,根据您的偏好进行配置)。当修复程序修复了失败的构建后,它将向提交者发送电子邮件。越来越多。Jenkins归档工件也使Jenkins每次构建时都可以使用它们。尽管不像SVN结帐那样重要,但这再次成为使其成为Jenkins不可或缺的一部分。与部署相同。除非您有一个环境,否则部署通常会发生在多个环境中。Jenkins可以通过使用Promotions来跟踪部署了特定版本(具有特定的SVN更改集)的环境。您正在接受所有这些。听起来您被告知“您必须使用Jenkins”,但您实际上并不想这样做,而这样做只是为了让您的老板松了一口气,只是打了勾号:“是的,我已经使用了Jenkins”

简短的答案是:Jenkin的Execute Shell构建步骤的最后一个命令的退出代码是确定Build Step成功/失败的原因。-成功-失败 注意,这是确定构建步骤的成功/失败,而不是整个作业的运行。整个作业运行的成功/失败会进一步受到多个构建步骤以及构建后操作和插件的影响。0anything else

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

最后,请在此处阅读Jenkins Build脚本,在执行Google Test后退出。它与您的问题没有直接关系,但请注意,有关Jenkins 作为外壳脚本启动Execute Shell构建步骤的部分/bin/sh -xe

-e意味着即使只有1条命令失败,即使您对该命令进行错误检查,shell脚本也会失败退出(因为该脚本在进行错误检查之前就退出了)。这与Shell脚本的正常执行相反,Shell脚本通常会打印失败命令的错误消息(或将其重定向为null并通过其他方式处理),然后继续执行。

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

由于您说脚本完成了所有应做的工作,因此失败的命令很可能位于脚本末尾。也许是最后的回声?还是某处的文物副本?没有看到完整的控制台输出,我们只是在猜测。

请发布作业运行的控制台输出,最好也发布shell脚本本身,然后我们才能确切告诉您哪一行失败。


6
我仍然使用Jenkins的原因尚不清楚...似乎最上层的人不太了解我们已经有了此脚本,并坚持要使用Jenkins。我觉得自己在迪尔伯特(Dilbert)地带。感谢您的-e提示。它解决了问题
测试人员

45
使用Jenkins仍然有充分的理由:审计跟踪,构建状态可见性等。如果已经有了构建脚本,则在将其重构为利用Jenkins功能之前,将其移至Jenkins是一个很好的第一步。
aehlke 2014年

3
交叉链接此答案serverfault.com/a/143576/186454可以在脚本的任何位置指定set + e和set -e。如果返回值不为0,两者之间的任何代码不会失败的构建
亚历Skrypnyk

2
在shell脚本vs jenkins上说得非常好
pushya

我们使用jenkins提供经过身份验证的访问权限和作业UI。一个cron不会削减它。詹金斯(Jenkins)不只是玩犯罪游戏。
ffghfgh

90

简单而简短的答案是

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

#!/bin/sh

现在,让我向您解释为什么我们需要此行来执行“执行Shell”构建作业。

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

因此,通过添加#!/bin/shwill将使您无法执行任何选择。


4
已投票。不知道-xe缺省值。当我的grep comman找不到字符串时,我的整个脚本失败了,因为grep返回了非零返回值:)
Somaiah Kumbera 2015年

很棒!在我的非关键步骤中使用它,即清理步骤,只能执行类似操作find . -name 'bower_components' -exec rm {} \;,在某些情况下,它是失败的。谢谢!
yorch '16

这清除了所有内容- “还有另一个选项-e,当任何命令以非零退出(当任何命令失败时)退出代码时,shell会立即停止运行脚本。”
Paramvir Singh Karwal

3

我认为,关闭-eshell 的选项不是一个好主意。最后,由于瞬态情况(例如磁盘空间不足或网络错误),脚本中的命令之一将失败。没有-e詹金斯,就不会注意到,并且会幸福地继续下去。如果您已设置Jenkins进行部署,则可能会导致不良代码被推送并导致您的网站瘫痪。

如果脚本中有一行预期会失败的行(例如grep或find),则只需添加|| true到该行的末尾即可。这样可以确保生产线始终返回成功。

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

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

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

grep foo bar || ret=$?

1
谢谢布莱恩。你救了我的日子。另外,我认为同时打开-x和-e是一个好主意。这样就可以在詹金斯日志中看到。
比卡勒·巴斯内

2

干净利落:

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

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

我从另一个角度写了类似的文章,但也许​​无论如何还是有帮助的: Jenkins为什么认为我的构建成功了?


0

因此,通过添加#!/bin/shwill将使您无法执行任何选择。

它还帮助我解决了在我的Linux从属服务器上执行来自Jenkins主服务器的bash脚本的问题。通过#!/bin/bash在“执行外壳”(Execute Shell)块中添加我的实际脚本之上,它解决了我的问题,否则它将执行Windows git提供的bash shell版本,从而产生错误。


0

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

$BUILD_NUMBER or ${BUILD_NUMBER}

在这种情况下,必须在另一个变量中进行设置。

set BUILDNO = $BUILD_NUMBER
$BUILDNO
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.