简体   繁体   English

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

[英]don't fail jenkins build if execute shell fails

As part of my build process, I am running a git commit as an execute shell step.作为构建过程的一部分,我将 git commit 作为执行 shell 步骤运行。 However, if there are no changes in the workspace, Jenkins is failing the build.但是,如果工作区中没有任何更改,Jenkins 将导致构建失败。 This is because git is returning an error code when there are no changes to commit.这是因为当没有提交更改时,git 会返回错误代码。 I'd like to either abort the build, or just mark it as unstable if this is the case.如果是这种情况,我想中止构建,或者只是将其标记为不稳定。 Any ideas?有任何想法吗?

To stop further execution when command fails:命令失败时停止进一步执行:

command || exit 0

To continue execution when command fails:命令失败时继续执行:

command || true

Jenkins is executing shell build steps using /bin/sh -xe by default.默认情况下,Jenkins 使用/bin/sh -xe执行 shell 构建步骤。 -x means to print every command executed. -x表示打印执行的每个命令。 -e means to exit with failure if any of the commands in the script failed. -e表示如果脚本中的任何命令失败则退出失败。

So I think what happened in your case is your git command exit with 1, and because of the default -e param, the shell picks up the non-0 exit code, ignores the rest of the script and marks the step as a failure.因此,我认为在您的情况下发生的事情是您的 git 命令以 1 退出,并且由于默认的-e参数,shell 会选择非 0 退出代码,忽略脚本的其余部分并将该步骤标记为失败。 We can confirm this if you can post your build step script here.如果您可以在此处发布构建步骤脚本,我们可以确认这一点。

If that's the case, you can try to put #!/bin/sh so that the script will be executed without option;如果是这种情况,您可以尝试放置#!/bin/sh以便脚本将在没有选项的情况下执行; or do a set +e or anything similar on top of the build step to override this behavior.或者在构建步骤之上执行set +e或任何类似的操作来覆盖此行为。


Edited: Another thing to note is that, if the last command in your shell script returns non-0 code , the whole build step will still be marked as fail even with this setup.编辑:另一件需要注意的事情是,如果您的 shell 脚本中的最后一个命令返回 non-0 code ,则即使使用此设置,整个构建步骤仍将被标记为失败。 In this case, you can simply put a true command at the end to avoid that.在这种情况下,您可以简单地在末尾放置一个true命令来避免这种情况。

Another related question另一个相关问题

If there is nothing to push git returns exit status 1. Execute shell build step is marked as failed respectively.如果没有任何推送git返回退出状态1。执行shell构建步骤分别标记为失败。 You can use OR statement ||您可以使用 OR 语句 || (double pipe). (双管)。

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

That means, execute second argument if first failed (returned exit status > 0).这意味着,如果第一次失败(返回退出状态 > 0),则执行第二个参数。 Second command always returns 0. When there is nothing to push (exit status 1 -> execute second command) echo will return 0 and build step continues.第二个命令总是返回 0。当没有任何东西要推送时(退出状态 1 -> 执行第二个命令)echo 将返回 0 并继续构建步骤。

To mark build as unstable you can use post-build step Jenkins Text Finder.要将构建标记为不稳定,您可以使用构建后步骤 Jenkins Text Finder。 It can go through console output, match pattern (your echo) and mark build as unstable.它可以通过控制台输出、匹配模式(您的回声)并将构建标记为不稳定。

There is another smooth way to tell Jenkins not to fail.还有另一种平滑的方法可以告诉 Jenkins 不要失败。 You can isolate your commit in a build step and set the shell to not fail:您可以在构建步骤中隔离您的提交并将 shell 设置为不失败:

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

Jenkins determines the success/failure of a step by the return value of the step. Jenkins 通过步骤的返回值确定步骤的成功/失败。 For the case of a shell, it should be the return of the last value.对于shell的情况,它应该是最后一个值的返回。 For both Windows CMD and (POSIX) Bash shells, you should be able to set the return value manually by using exit 0 as the last command.对于 Windows CMD 和 (POSIX) Bash shell,您应该能够通过使用exit 0作为最后一个命令来手动设置返回值。

I was able to get this working using the answer found here:我能够使用这里找到的答案来解决这个问题:

How to git commit nothing without an error? 如何 git commit 没有错误?

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

On the (more general) question in title - to prevent Jenkins from failing you can prevent it from seeing exit code 1. Example for ping:关于标题中的(更一般的)问题 - 为防止 Jenkins 失败,您可以防止它看到退出代码 1。ping 示例:

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

And now you can eg get output of ping:现在你可以得到 ping 的输出:

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

Of course instead of ping ... You can use any command(s) - including git commit .当然,而不是ping ...您可以使用任何命令 - 包括git commit

https://jenkins.io/doc/pipeline/steps/workflow-durable-task-step/#sh-shell-script https://jenkins.io/doc/pipeline/steps/workflow-durable-task-step/#sh-shell-script

if you include a returnStatus: true property, then the shell return is ignored.如果包含 returnStatus: true 属性,则忽略 shell 返回值。

This answer is correct, but it doesn't specify the || exit 0这个答案是正确的,但它没有指定|| exit 0 || exit 0 or || true || exit 0|| true || true goes inside the shell command . || true进入shell command Here's a more complete example:这是一个更完整的示例:

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

The above will work, but the following will fail:以上将工作,但以下将失败:

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

Perhaps it's obvious to others, but I wasted a lot of time before I realized this.也许这对其他人来说是显而易见的,但我在意识到这一点之前浪费了很多时间。

You can use the Text-finder Plugin .您可以使用 文本查找器插件 It will allow you to check the output console for an expression of your choice then mark the build as Unstable .它将允许您检查输出控制台以获取您选择的表达式,然后将构建标记为Unstable

For multiple shell commands, I ignores the failures by adding:对于多个 shell 命令,我通过添加以下内容来忽略失败:

set +e commands true

在此处输入图片说明

If you put this commands into shell block:如果将此命令放入 shell 块中:

false
true

your build will be marked as fail ( at least 1 non-zero exit code ), so you can add (set +e) to ignore it:您的构建将被标记为失败(至少 1 个非零退出代码),因此您可以添加 (set +e) 以忽略它:

set +e
false
true

will not fail.不会失败。 However, this will fail even with the (set +e) in place:但是,即使 (set +e) 到位,这也会失败:

set +e
false

because the last shell command must exit with 0.因为最后一个 shell 命令必须以 0 退出。

The following works for mercurial by only committing if there are changes.以下仅在有更改时提交才适用于mercurial So the build only fails if the commit fails.所以只有在提交失败时构建才会失败。

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

Another one answer with some tips, can be helpful for somebody:另一个带有一些提示的答案,可能对某人有所帮助:

remember to separate your commands with the following rule :请记住使用以下规则分隔您的命令:

command1 && command2 - means, that command2 will be executed, only if command1 success command1 && command2 - 意味着,仅当 command1 成功时才会执行 command2

command1 ;命令 1 ; command2 - means, that command 2 will be executed despite on result of command1 command2 - 意味着,不管 command1 的结果如何,命令 2 都会被执行

for example:例如:

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

will be executed successfully with set -e and echo 0 commands if gmake test failed (your tests failed), while the following code snipped:如果gmake test失败(您的测试失败),将使用set -eecho 0命令成功执行,同时截断以下代码:

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

a bit wrong and commands set -e and echo 0 in && gmake test && set -e && echo 0 will be skipped, with the println run_tests statement, because failed gmake test will abort the jenkins build.有点错误,命令set -eecho 0 in && gmake test && set -e && echo 0将被跳过,使用println run_tests语句,因为失败的gmake test将中止 jenkins 构建。 As workaround you can switch to returnStatus:true , but then you will miss the output from your command.作为解决方法,您可以切换到returnStatus:true ,但是您将错过命令的输出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM