Как / когда выполнение оболочки помечает сборку как сбой в Jenkins?

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

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

  • проверяет источники из SVN
  • построить проект
  • развертывает проект
  • убирает за собой

поэтому в Jenkins мне нужно только "построить" проект, запустив скрипт в команде Execute Shell. Сценарий выполняется (The источники загружаются, проект строится/развертывается), но затем он помечает сборку как сбой: Шаг сборки "Execute shell" помечен как build как failure Даже если сценарий был успешно запущен! Я попытался закрыть скрипт:

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

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

6 ответов


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

если у вас есть сценарий оболочки, который делает "checkout, build, deploy" сам по себе, то почему вы используете Jenkins? Вы отказываетесь от всех особенностей Дженкинса, которые делают его тем, что он есть. у вас также может быть cron или SVN post-commit hook, вызывающий скрипт напрямую. Дженкинс, выполняющий сам svn checkout, имеет решающее значение. Он позволяет запускать сборки только при наличии изменений (или по таймеру, или вручную, если вы предпочитаете). Он отслеживает изменения между сборками. Он показывает эти изменения, поэтому вы можете видеть, какая сборка была для какого набора изменений. Он отправляет сообщения по электронной почте, когда их изменения вызвали успешную или неудачную сборку (опять же, как вы предпочитаете). Он вышлет коммиттеров для их исправления исправлены ошибки построения. И все больше и больше. Архивация артефактов Jenkins также делает их доступными для каждой сборки, прямо как Дженкинс. Хотя это не так важно, как проверка SVN, это снова неотъемлемая часть того, что делает его Дженкинсом. То же самое с развертыванием. Если у вас нет одной среды, развертывание обычно происходит в нескольких средах. Дженкинс может отслеживать, в какой среде развернута конкретная сборка (с определенным набором изменений SVN), с помощью рекламных акций. Вы отказываетесь от всего этого. Похоже, вам говорят: "Вы должны использовать Дженкинса", но вы действительно не хотите, и вы делаете это только для того, чтобы ваши боссы отвязались от вас, просто чтобы поставить галочку "да, я использовал Дженкинса"

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

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

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

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

чтобы обойти это, добавьте set +e в верхней части вашего скрипта.

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

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


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

пожалуйста, добавьте следующую строку в шаг сборки "Execute shell".

#!/bin/sh

теперь позвольте мне объяснить вам, почему нам нужна эта строка для задания сборки "выполнить оболочку".

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

добавить в #!/bin/sh позволит вам выполнить не вариант.


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

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

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

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


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

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

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

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

или вы можете захватить код возврата в свой || статья:

grep foo bar || ret=$?

добавить в #!/bin/sh позволит вам выполнить не вариант.

Это также помогло мне в устранении проблемы, когда я выполнял скрипт bash от Jenkins master на моем Linux slave. Просто добавив #!/bin/bash над моим фактическим скриптом в блоке "Execute Shell" он исправил мою проблему, поскольку в противном случае он выполнял windows git предоставленную версию оболочки bash, которая давала ошибку.


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

$BUILD_NUMBER или ${BUILD_NUMBER}

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

установить BUILDNO = $BUILD_NUMBER $ BUILDNO