Сразу о главном страхе: jenkins error 503 при заходе в интерфейс или при обращении агента к контроллеру. Это не про твой Jenkinsfile - это про сам сервер или прокси перед ним. Разберём и это тоже, потому что спрос на "почему 503" огромный, а причина почти всегда одна и та же.
Где именно упало: анатомия лога сборки
Любой troubleshooting в Jenkins начинается с одного вопроса - на каком шаге оборвалось выполнение. Конвейер declarative исполняется сверху вниз по стадиям, и в момент падения Jenkins останавливается ровно на провалившемся шаге. Твоя задача - найти эту точку.
Открывай Console Output - полный сырой лог сборки. Он линейный: команды, их вывод, служебные сообщения Jenkins. Самое полезное - искать с конца. Падение почти всегда сопровождается строкой вида:
Код: Выделить всё
+ npm run build
sh: 1: npm: not found
script returned exit code 127
- exit code 0 - успех, всё хорошо;
- exit code 1 - generic ошибка, смотри вывод команды выше;
- exit code 2 - часто синтаксис в bash или misuse шелла;
- exit code 126 - файл найден, но не исполняемый (нет +x или это не бинарь);
- exit code 127 - команда не найдена (нет инструмента в PATH);
- exit code 137 - процесс убит сигналом 9 (128+9), почти всегда OOM - не хватило памяти;
- exit code 143 - убит сигналом 15 (128+15), обычно таймаут или отмена сборки.
В Pipeline лог Jenkins заботливо разбивает на сворачиваемые блоки по стадиям и шагам - это представление Pipeline Steps (старый Pipeline Steps view плюс встроенная подсветка стадий в современном UI). Провалившаяся стадия подсвечена красным, можно сразу провалиться внутрь и увидеть лог конкретного шага, не листая весь Console Output. На больших конвейерах это экономит минуты.

Jenkins build failed: типичные причины и как их опознать
Когда видишь jenkins build failed, не угадывай - читай. Большинство ошибок укладывается в несколько повторяющихся сценариев, и каждый имеет узнаваемую сигнатуру в логе.
Команда вернула ненулевой код. Базовый случай. Шаг sh падает, если процесс завершился не нулём. Лог покажет вывод и exit code. Лечится починкой самой команды. Подводный камень: пайп. В строке
Код: Выделить всё
sh 'cat file | grep foo'Не найден инструмент или агент. Сигнатура - exit code 127 и "not found", либо сборка вечно висит в очереди с надписью про отсутствие подходящего агента. Первое - проблема окружения агента (нет node, docker, jdk), второе - неправильный label в директиве agent. Проверь, что лейбл в Jenkinsfile реально существует на каком-то агенте.
Нет прав. "Permission denied", exit code 126 или 13. Частая боль - доступ к docker.sock внутри агента или запись в чужую директорию. В Kubernetes сюда же относятся отказы RBAC service account.
Таймаут. Сборка обрывается по времени с явным сообщением про timeout. Это не баг, а твоя же директива options { timeout(...) }, отрабатывающая по плану. Если таймаут ложный - команда реально медленная, не вешай костыль, разбирайся с причиной.
Проблема с кредами. Самое коварное, потому что Jenkins маскирует секреты в логе звёздочками, и ты видишь "authentication failed" без значения. Признаки: 401/403 от registry или git, "could not read Username", "Bad credentials". Проверяй ID credentials в блоке environment и то, что биндинг реально подставился.
Вот компактный пример с диагностикой, который ловит и логирует код возврата руками, не давая Jenkins молча упасть:
Код: Выделить всё
pipeline {
agent { label 'linux' }
options {
timeout(time: 15, unit: 'MINUTES')
timestamps()
}
environment {
REG = credentials('docker-registry-creds')
}
stages {
stage('Build') {
steps {
script {
def code = sh(
script: 'set -o pipefail; npm ci && npm run build 2>&1 | tee build.log',
returnStatus: true
)
if (code != 0) {
echo "Шаг сборки упал, exit code ${code}"
sh 'tail -n 40 build.log || true'
error("Build failed with code ${code}")
}
}
}
}
}
post {
failure {
archiveArtifacts artifacts: 'build.log', allowEmptyArchive: true
}
}
}
Временные метки, системные журналы и воспроизведение через Replay
Когда сбой не очевиден, в ход идут три инструмента посерьёзнее.
Временные метки (timestamps). По умолчанию строки лога без времени, и понять "что тут зависло на 8 минут" невозможно. Опция timestamps() из плагина Timestamper добавляет к каждой строке отметку времени. Включается на конвейер в options или глобально для всех сборок. После этого в логе видно
Код: Выделить всё
[2026-06-15T10:42:13.880Z]Системные журналы Jenkins. Если проблема не в твоём коде, а в самом Jenkins - смотри Manage Jenkins -> System Log. Это внутренние логи контроллера: ошибки плагинов, отвалы агентов, проблемы с потоками. На сервере те же события пишутся в обычный лог процесса. Под systemd достаточно:
Код: Выделить всё
journalctl -u jenkins -f --since "10 min ago"
Код: Выделить всё
# в логе nginx
upstream prematurely closed connection ... 503
# в это же время в journalctl jenkins
Jenkins is fully up and running <- появится позже
Воспроизведение через Replay. Лучший инструмент отладки самого Jenkinsfile. В меню сборки слева есть Replay - он открывает редактор с тем же самым сценарием, что выполнялся, ты правишь любую строку и запускаешь заново, не делая коммит в git. Идеально для отладки сломанной логики: добавил echo, поменял команду, прогнал, повторил. Replay работает и на падавших сборках, и итеративно сколько угодно раз. Когда нашёл рабочий вариант - переносишь правку в репозиторий уже осознанно.
Отдельный навык - поиск строки сценария, вызвавшей ошибку. Если упал не sh, а сам Groovy (например, обращение к null), Jenkins выдаёт stack trace, и в нём есть строки вида
Код: Выделить всё
at WorkflowScript.run(WorkflowScript:23)Грабли, мини-лаба и контрольные вопросы
Типичные грабли при чтении логов:
- Маскировка секретов сбивает с толку - "***" в логе это не баг, Jenkins прячет credentials. Не ищи там реальное значение, проверяй сам биндинг.
- sh без pipefail прячет падение в середине пайпа - сборка зелёная, а на деле сломалась. Всегда set -o pipefail для критичных пайпов.
- Лог стадии в Pipeline Steps и общий Console Output - это одно и то же, но в разной нарезке. Не паникуй, что "логи разные".
- exit code 137 списывают на флапающий тест, а это OOM. Проверь memory limit агента, особенно в Kubernetes.
- Номер строки из stack trace относится к Jenkinsfile в его исполняемом виде, а не к твоему файлу с комментариями - сверяйся через Replay, там нумерация честная.
- 503 при заходе путают с упавшей сборкой. 503 - это слой инфраструктуры (proxy + старт + память контроллера), а не твой pipeline.
- Сделай заведомо падающий шаг и найди в Console Output строку с exit code. Какой код?
Код: Выделить всё
sh 'somecommandthatdoesnotexist' - Включи timestamps() в options и сравни лог до и после - где видны паузы.
- Вставь в шаг искусственный sleep на минуту и под timeout(time: 30, unit: 'SECONDS') поймай код 143 в логе.
- Открой Replay, добавь echo перед падающим шагом, запусти и убедись, что коммита в git не было.
- Зайди в Manage Jenkins -> System Log и найди записи о старте последней сборки.
- Какой exit code говорит "команда не найдена", а какой - "процесс убит по нехватке памяти"?
- Чем Replay отличается от обычного Rebuild и почему он удобнее для отладки Jenkinsfile?
- Где смотреть причину, если jenkins error 503 не пускает в интерфейс - в логе сборки или где-то ещё?
- Зачем нужен set -o pipefail и какую ошибку он помогает не пропустить?
Чтение логов - это не магия, а алгоритм: открыл Console Output, прокрутил в конец, нашёл exit code, по коду понял класс проблемы, по строке stack trace нашёл место в сценарии, через Replay починил без коммита. Системные журналы и timestamps подключаешь, когда сбой не в коде, а в инфраструктуре. А 503 запомни как отдельную категорию - это почти всегда proxy и память контроллера, а не твой конвейер. Освой этот маршрут до автоматизма, и любой jenkins build failed превращается из паники в пятиминутную диагностику.