如果执行shell失败,请不要让jenkins构建失败


132

作为构建过程的一部分,我正在将git commit作为execute shell步骤运行。但是,如果工作区中没有任何更改,则Jenkins将使构建失败。这是因为当没有要提交的更改时,git返回错误代码。我想中止构建,或者只是在这种情况下将其标记为不稳定。有任何想法吗?


检查是否有任何要提交的内容,仅在那些情况下才提交? stackoverflow.com/questions/5139290/...
安德斯·林达尔

Answers:


210

要在命令失败时停止进一步执行:

command || exit 0

要在命令失败时继续执行:

command || true


12
|| exit 0在第一种情况下,您不需要,如果command返回false,则执行将停止。也就是说,第二种选择非常有帮助!
尼尔·阿法西

20
@alfasin您不明白问题所在。OP不希望Jenkins构建失败;因此,我们必须这样做,exit 0因为任何非零的退出代码都会使构建失败。
Quolonel问题

1
我看到,在那种情况下,我将措辞从:“在命令失败时停止进一步执行:”改为:“在命令失败并将Jenkins作业标记为成功时停止进一步执行:”。
Nir Alfasi 2015年

1
@alfasin虽然我同意Quolonel Questions简短的言论是不专业的,但他说的没错。“退出0”不会标记作业成功。它只会标记当前的构建步骤成功。在下一个构建步骤之一中,作业仍可能失败。
noamik 2015年

1
谢谢你的工作!这对于“使用ssh在远程主机上执行Shell”插件功能特别有用,因为您不能使用/ bin / bash + e来确保不会因错误而失败。我也喜欢这样的想法:选择哪些命令不会使构建失败。
leeman24 '17

80

Jenkins /bin/sh -xe默认使用Shell执行步骤。-x表示打印每个执行的命令。-e表示如果脚本中的任何命令失败,则退出失败。

因此,我认为您遇到的情况是您的git命令以1退出,由于默认-e参数,shell选取了非0的退出代码,忽略了脚本的其余部分并将该步骤标记为失败。如果您可以在此处发布构建步骤脚本,我们可以确认。

如果是这种情况,您可以尝试放置,#!/bin/sh以便脚本可以不带选项地执行;或set +e在构建步骤顶部执行或类似操作以覆盖此行为。


编辑:需要注意的另一件事是,如果shell脚本中的最后一个命令返回非0代码,则即使使用此设置,整个构建步骤仍将标记为失败。在这种情况下,您只需echo在末尾放置一个命令即可避免这种情况。

另一个相关的问题


41

如果没有要推送的内容,git将返回退出状态1.执行shell生成步骤分别标记为失败。您可以使用OR语句|| (双管)。

git commit -m 'some messasge' || echo 'Commit failed. There is probably nothing to commit.'

这意味着,如果第一个失败(返回的退出状态> 0),则执行第二个参数。第二个命令始终返回0。当没有任何要推送的内容(退出状态1->执行第二个命令)时,echo将返回0,并且继续执行构建步骤。

要将构建标记为不稳定,可以使用构建后步骤Jenkins Text Finder。它可以通过控制台输出,匹配模式(您的回声)并将构建标记为不稳定。


27

还有另一种平滑的方法告诉詹金斯不要失败。您可以在构建步骤中隔离提交,并将外壳设置为不失败:

set +e
git commit -m "Bla."
set -e

2
确保set -e在要运行的命令后添加,无论退出代码如何。否则,您可能最终会执行不需要的命令。我想自己处理该错误,所以我做了类似的事情:`set + e commit -m“ bla” EXIT_CODE =“ $ {?}” set -e#处理退出代码逻辑`
jcasner,

8

Jenkins通过步骤的返回值确定步骤的成功/失败。对于shell,应该是最后一个值的返回。对于Windows CMD和(POSIX)Bash Shell,您都应该能够通过使用exit 0last命令来手动设置返回值。


这似乎不适用于具有两行代码的“执行Windows蝙蝠”:git commit -m“ message” exit 0
Ben

@Ben exit 0在Windows Jenkins安装的多个版本中与“ execute windows batch command”一起使用,它可以按预期工作。还必须进行其他操作。您可以发布控制台日志的相关部分吗?
jwernerny13年

您在第一步中将其与git commit -m“ blah”一起使用吗?我尝试在计算机上手动创建bat脚本,并在git命令后放置echo和exit 0。当没有任何要提交的命令时,其他命令均不会运行...
2013年

请参阅@xiawei的答案。Jenkins的默认行为是执行shell,#!/bin/sh -xv如果遇到任何错误,将使用该shell 停止脚本。
轻松逗乐的史蒂文(Steven the Easy)

8

我能够使用此处找到的答案使此工作正常进行:

如何在没有错误的情况下git commit什么?

git diff --quiet --exit-code --cached || git commit -m 'bla'

1
上面的操作是:“执行git diff命令,如果失败,则执行git commit命令。基本上,只有git diff找到了要提交的内容,它才执行提交。但是@jwernerny回答是正确的,您应该可以将其添加exit 0为最后一条语句到让Jenkins视为成功的任何脚本。我可以想到一个方案,如果您执行Linux Shell步骤,该方案将失败,但在批处理中应始终有效
Slav 2013年

@Ben Jenkins /bin/sh -xe默认使用此处提到的(中间)执行Shell构建步骤。因此,您可以尝试在构建步骤的顶部放置一个#!/bin/bash或执行一个set +e操作来覆盖此行为,即使在退出时使用非0代码退出一个命令,也将继续执行该步骤的其余部分
Xiawei Zhang

8

关于标题中的(更一般的)问题-为防止Jenkins失败,您可以防止其看到退出代码1。ping示例:

bash -c "ping 1.2.3.9999 -c 1; exit 0"

现在您可以例如获取ping的输出:

output=`bash -c "ping 1.2.3.9999 -c 1; exit 0"`

当然,ping ...您可以使用任何命令来代替-包括git commit



6

您可以使用Text-finder插件。它将允许您在输出控制台中检查您选择的表达式,然后将构建标记为Unstable


这看起来很有希望,但是由于某种原因它一直使构建失败。

4

对于多个shell命令,我通过添加以下内容来忽略故障:

set +e commands true

在此处输入图片说明


我一般不鼓励设置-e。如果要忽略某些特定命令的返回值,则可以添加“ || true”或更有意义的返回true,例如:stop-service.sh || echo服务已经下降
劳尔·萨利纳斯,蒙特阿古

3

如果将此命令放入shell块中:

false
true

您的构建将被标记为失败(至少1个非零退出代码),因此您可以添加(set + e)来忽略它:

set +e
false
true

不会失败。但是,即使设置了(set + e),这也将失败:

set +e
false

因为最后一个shell命令必须以0退出。


2

以下适用于水银仅如果有变化犯。因此,仅在提交失败时构建才会失败。

hg id | grep "+" || exit 0
hg commit -m "scheduled commit"

0

另一个包含一些提示的答案可能对某人有帮助:

请记住使用以下规则分隔命令:

command1 && command2-表示仅在command1成功的情况下才会执行command2

command1 ; command2-表示尽管有command1的结果,仍将执行命令2

例如:

String run_tests = sh(script: "set +e && cd ~/development/tests/ && gmake test ;set -e;echo 0 ", returnStdout: true).trim()
println run_tests 

如果失败(您的测试失败),将通过set -eecho 0命令成功执行gmake test(您的测试失败),同时以下代码被截断:

String run_tests = sh(script: "set +e && cd ~/development/tests/ && gmake test && set -e && echo 0 ", returnStdout: true).trim()
println run_tests 

有点错误,命令set -eecho 0in && gmake test && set -e && echo 0将被该println run_tests语句跳过,因为失败gmake test将中止jenkins构建。解决方法是,您可以切换到returnStatus:true,但是随后您将错过命令的输出。


0

这个答案是正确的,但它没有指定|| exit 0|| true进入shell命令里面。这是一个更完整的示例:

sh "adb uninstall com.example.app || true"

上面的方法可以工作,但是以下操作将失败:

sh "adb uninstall com.example.app" || true

也许对其他人来说很明显,但是我花了很多时间才意识到这一点。

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.