Как / когда Execute Shell отмечает сборку как сбой в Jenkins?

112

Ужасные истории, которые я нашел в поисках ответа на этот вопрос ...

Хорошо, у меня есть сценарий .sh, который делает практически все, что должен делать Дженкинс:

  • проверяет источники из SVN
  • построить проект
  • разворачивает проект
  • очищает после себя

Таким образом, в Jenkins мне нужно только «построить» проект, запустив сценарий в команде Execute Shell. Сценарий запускается (исходники загружаются, проект строится / развертывается), но затем он отмечает сборку как сбой: на этапе сборки «Выполнить оболочку» сборка помечена как сбой, даже если сценарий был успешно запущен! Я попытался закрыть скрипт с помощью:

  • выход 0 (все еще помечает это как сбой)
  • выход 1 (помечает это как сбой, как и ожидалось)
  • вообще нет команды выхода (помечает это как сбой)

Когда, как и почему Execute Shell отмечает мою сборку как неудачную?

тестер
источник

Ответы:

131

Перво-наперво наведите указатель мыши на серую область ниже. Это не часть ответа, но абсолютно необходимо сказать:

Если у вас есть сценарий оболочки, который выполняет «проверку, сборку, развертывание» сам по себе, то почему вы используете Jenkins? Вы отказываетесь от всех функций Jenkins, которые делают его тем, чем он является. У вас также может быть хук после фиксации cron или SVN, напрямую вызывающий скрипт. Сам Дженкинс, выполняющий проверку SVN, имеет решающее значение. Это позволяет запускать сборки только при внесении изменений (или по таймеру, или вручную, если хотите). Он отслеживает изменения между сборками. Он показывает эти изменения, поэтому вы можете видеть, какая сборка для какого набора изменений. Он отправляет коммиттерам электронные письма, когда их изменения привели к успешной или неудачной сборке (опять же, в соответствии с вашими предпочтениями). Он отправит коммиттерам электронное письмо, когда их исправления исправят неудачную сборку. И еще и еще. Архивирование артефактов Дженкинсом также делает их доступными для каждой сборки прямо из Дженкинса. Хотя это не так важно, как проверка SVN, это снова неотъемлемая часть того, что делает его Jenkins. То же самое и с развертыванием. Если у вас нет единой среды, развертывание обычно происходит в нескольких средах. Jenkins может отслеживать, в какой среде развернута конкретная сборка (с определенным набором изменений SVN), с помощью рекламных акций. Вы отказываетесь от всего этого. Похоже, вам говорят «вы должны использовать Jenkins», но на самом деле вы этого не хотите, и вы делаете это только для того, чтобы избавиться от своих боссов, просто чтобы поставить галочку «да, я использовал Jenkins»

Короткий ответ: код выхода последней команды этапа сборки Jenkin Execute Shell определяет успех / неудачу этапа сборки . 0- успех, anything else- неудача. Обратите внимание, что это определяет успех / неудачу этапа сборки , а не всего выполнения задания . На успех / неудачу всего выполнения задания могут в дальнейшем повлиять несколько шагов сборки, а также действия и плагины после сборки.

Вы упомянули Build step 'Execute shell' marked build as failure, поэтому мы сосредоточимся только на одном этапе сборки. Если на этапе сборки « Выполнить оболочку» есть только одна строка, которая вызывает сценарий оболочки, то код выхода сценария оболочки будет определять успех / сбой этапа сборки. Если после выполнения сценария оболочки у вас осталось больше строк, внимательно просмотрите их, поскольку именно они могут вызывать сбой.

Наконец, прочтите здесь Jenkins Build Script завершается после выполнения Google Test . Это не имеет прямого отношения к вашему вопросу, но обратите внимание на то, что Дженкинс запускает этап сборки Execute Shell в виде сценария оболочки с/bin/sh -xe

В -eозначает , что сценарий оболочки будет выйти из неудачи, даже если только одна команды выходит из строя, даже если вы делаете проверку ошибок для этой команды (из - за выходы сценария , прежде чем он доберется до вашей проверки ошибок). Это противоречит нормальному выполнению сценариев оболочки, которые обычно выводят сообщение об ошибке для неудачной команды (или перенаправляют его на null и обрабатывают другими способами) и продолжают.

Чтобы обойти это, добавьте set +eв начало сценария оболочки.

Поскольку вы говорите, что ваш сценарий делает все, что от него требуется, скорее всего, сбойная команда находится где-то в конце сценария. Может, финальное эхо? Или где-нибудь скопировать артефакты? Не видя полного вывода консоли, мы просто предполагаем.

Пожалуйста, опубликуйте вывод консоли выполнения задания и, желательно, сам сценарий оболочки, и тогда мы сможем вам точно сказать, какая строка не работает.

Славянин
источник
6
Причина, по которой я все еще использую Jenkins, мне неясна ... Кажется, кто-то наверху не совсем понял, что у нас уже есть этот сценарий, и настоял на том, чтобы мы использовали Jenkins. Я чувствую себя так, будто попал в полосу Дилберта. Спасибо за подсказку. Решил проблему
tester
45
По-прежнему есть веские причины для использования Jenkins: контрольный журнал, видимость состояния сборки и т. Д. Если у вас уже есть сценарий сборки, перемещение его в Jenkins - хороший первый шаг перед его рефакторингом для использования возможностей Jenkins.
aehlke
3
Перекрестная ссылка на этот ответ serverfault.com/a/143576/186454 set + e и set -e может быть указана в любом месте вашего скрипта. Любой промежуточный код не приведет к сбою сборки, если возвращаемое значение не равно 0.
Алекс Скрипник,
2
очень хорошо сказано о сценарии оболочки против набора
Дженкинса
мы используем jenkins для обеспечения аутентифицированного доступа и пользовательского интерфейса для работы. Крон не стал бы резать. Дженкинс не просто запускает скрипты.
ffghfgh
90

Простой и короткий ответ на ваш вопрос:

Добавьте следующую строку в шаг сборки «Выполнить оболочку».

#!/bin/sh

Теперь позвольте мне объяснить вам причину, по которой нам нужна эта строка для задания сборки «Execute Shell».

По умолчанию Jenkins принимает, /bin/sh -xeи это означает, что -xбудет печататься каждая команда. И другой параметр -e, который заставляет оболочку немедленно прекращать запуск сценария, когда любая команда завершается с ненулевым (при сбое любой команды) кодом выхода.

Таким образом, добавление #!/bin/shпозволит вам выполнять без каких-либо опций.

Абхиджит Камбл
источник
4
Upvoted. Не знал о параметре -xe по умолчанию. Когда моя команда grep не находила строку, весь мой скрипт завершился неудачно, потому что grep вернул значение,
отличное от
Сработало отлично! Используя его на моем из второстепенных шагов, шаге очистки, который просто делает что-то вроде, find . -name 'bower_components' -exec rm {} \;а в некоторых случаях он терпит неудачу. Спасибо!
Йорч
это очистило все - «И другой параметр -e, который заставляет оболочку немедленно прекращать выполнение сценария, когда любая команда завершается с ненулевым (при сбое любой команды) кодом выхода».
Paramvir Singh Karwal
3

На мой взгляд, отключение этой -eопции в вашей оболочке - действительно плохая идея. В конце концов, одна из команд в вашем скрипте выйдет из строя из-за переходных условий, например нехватки места на диске или сетевых ошибок. Без -eДженкинса не заметит и продолжит счастливо. Если у вас есть Jenkins, настроенный для развертывания, это может привести к тому, что плохой код будет вытолкнут и выйдет из строя ваш сайт.

Если в вашем скрипте есть строка, в которой ожидается сбой, например, grep или find, просто добавьте || trueв конец этой строки. Это гарантирует, что строка всегда будет возвращать успех.

Если вам нужно использовать этот код выхода, вы можете либо поднять команду в свой оператор if:

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

Или вы можете записать код возврата в своем ||предложении:

grep foo bar || ret=$?
Брайан Ларсен
источник
1
Спасибо, Брайан. Ты спас мне день. Кроме того, я считаю хорошей идеей включить и -x, и -e. Чтобы вы увидели в своем журнале jenkins.
Бикал Баснет
2

Легко и просто:

Если Дженкинс видит, что этап сборки (который тоже является сценарием) завершается с ненулевым кодом, сборка отмечается красным шариком (= сбой).

Почему именно это происходит, зависит от вашего сценария сборки.

Я написал нечто подобное с другой точки зрения, но, может быть, это все равно поможет прочитать: почему Дженкинс считает, что моя сборка прошла успешно?

STI
источник
0

Таким образом, добавление #!/bin/shпозволит вам выполнять без каких-либо опций.

Это также помогло мне решить проблему, при которой я выполнял сценарий bash из мастера Jenkins на моем подчиненном устройстве Linux. Просто добавив #!/bin/bashвыше мой фактический скрипт в блок «Execute Shell», он устранил мою проблему, так как в противном случае он выполнял версию оболочки bash, предоставленную Windows git, которая выдавала ошибку.

Шайлендер Сингх
источник
0

В Jenkins ver. 1.635 невозможно отобразить собственную переменную среды, подобную этой:

$BUILD_NUMBER or ${BUILD_NUMBER}

В этом случае вы должны установить его в другой переменной.

set BUILDNO = $BUILD_NUMBER
$BUILDNO
user10413452
источник