Быстрое устранение неполадок сборок с помощью Jenkins CLI
Используйте Jenkins CLI для проверки неудачных сборок, потоковой передачи логов, проверки параметров и повторного запуска заданий без погружения в интерфейс.
Быстрое устранение неполадок сборок с помощью Jenkins CLI
Веб-интерфейс Jenkins полезен при исследовании. Jenkins CLI лучше, когда вы уже знаете имя задания, вам нужен лог сейчас или вы хотите повторять одни и те же проверки без кликов по страницам.
Неудачная сборка обычно требует три части информации: что выполнялось, где произошел сбой и что изменилось с последнего успешного запуска. CLI может быстро получить все три, если настроить его один раз.
Настройка повторяемой команды CLI
Скачайте CLI-банку с вашего контроллера Jenkins:
curl -O "$JENKINS_URL/jnlpJars/jenkins-cli.jar"
Используйте API-токен, а не пароль от учетной записи:
export JENKINS_URL="https://jenkins.example.com"
export JENKINS_USER="your-user"
export JENKINS_API_TOKEN="your-api-token"
alias jcli='java -jar jenkins-cli.jar -s "$JENKINS_URL" -auth "$JENKINS_USER:$JENKINS_API_TOKEN"'
Проверьте аутентификацию перед устранением реальной неисправности:
jcli who-am-i
jcli help
Если это не работает, сначала исправьте доступ к CLI. Частые причины: неправильный URL, токен с лишним пробелом, отсутствие разрешений или настройка безопасности Jenkins, отключающая используемый транспорт CLI.
Для общих скриптов избегайте алиасов оболочки. Оберните команду в небольшой скрипт или используйте переменные окружения в хранилище секретов CI, чтобы токены не попадали в историю оболочки.
Найдите неудачную сборку
Если вы знаете имя задания и номер сборки, переходите сразу к консольному логу. Если вы знаете только, что что-то недавно упало, начните с Groovy через CLI:
jcli groovy = <<'EOF'
Jenkins.instance.getAllItems(hudson.model.Job.class).each { job ->
def b = job.getLastBuild()
if (b != null && b.result == hudson.model.Result.FAILURE) {
println "${job.fullName} #${b.number} ${b.getTime()}"
}
}
EOF
Для папок и многоконвейерных пайплайнов используйте полное имя задания, как его знает Jenkins. Задание ветки может выглядеть так:
team-service/main
team-service/PR-42
folder-a/folder-b/deploy-prod
Если имя содержит пробелы, заключайте его в кавычки в оболочке:
jcli console "Folder With Spaces/My Pipeline" 128
Сначала получите консольный лог
Консольный лог по-прежнему является самым быстрым источником истины для большинства сбоев:
jcli console MyPipelineJob 123
Для длинных логов сохраните копию и ищите с контекстом:
jcli console MyPipelineJob 123 > build-123.log
grep -niE "error|failed|exception|traceback|permission denied|timeout" build-123.log | head -40
grep -niC 3 "permission denied" build-123.log
Не полагайтесь только на первую строку, содержащую "error". Инструменты сборки часто выводят предупреждения, имена тестов или ожидаемый текст ошибки. Ищите первую значимую ошибку после начала этапа, затем читайте строки перед ней. Причина часто находится выше стека вызовов.
Для выполняющейся сборки следите за логом:
jcli console MyPipelineJob 123 -f
Некоторые версии Jenkins и режимы CLI принимают --follow; другие используют -f. Проверьте jcli help console на вашем контроллере.
Определите этап, на котором произошел сбой
Логи пайплайнов включают маркеры этапов. Ищите их рядом с ошибкой:
grep -n "\[Pipeline\] stage" build-123.log
Затем проверьте раздел после последнего маркера этапа перед ошибкой. Если лог зашумлен, откройте его с помощью less:
less build-123.log
Внутри less ищите /ERROR, /Exception или /[Pipeline] stage.
Хороший Jenkinsfile упрощает это, выводя четкие имена шагов перед рискованными операциями:
echo 'Installing npm dependencies'
sh 'npm ci'
echo 'Running unit tests'
sh 'npm test'
Если каждый шаг — это просто sh './ci.sh', CLI все равно может получить лог, но лог может не дать достаточно информации. В этом случае улучшите пайплайн после инцидента.
Проверьте параметры и причины
Сборка может упасть из-за неправильной ветки, окружения или устаревшего параметра. Получите метаданные сборки с помощью Groovy:
jcli groovy = <<'EOF'
def job = Jenkins.instance.getItemByFullName('MyPipelineJob')
def build = job?.getBuildByNumber(123)
if (build == null) {
println 'Build not found'
return
}
println "Job: ${job.fullName}"
println "Build: #${build.number}"
println "Result: ${build.result}"
println "Duration: ${build.durationString}"
println 'Causes:'
build.getCauses().each { println "- ${it.shortDescription}" }
println 'Parameters:'
build.getAction(hudson.model.ParametersAction)?.parameters?.each {
println "- ${it.name}=${it.value}"
}
EOF
Это особенно полезно для заданий развертывания. Неудачное развертывание продакшена с BRANCH=feature/test — это совсем другая проблема, чем неудачное развертывание ожидаемого релизного тега.
Будьте осторожны при выводе переменных окружения. Они могут содержать секреты. Если нужны детали окружения, выводите конкретные безопасные ключи, а не дамп всего:
jcli groovy = <<'EOF'
def job = Jenkins.instance.getItemByFullName('MyPipelineJob')
def build = job?.getBuildByNumber(123)
def env = build?.getEnvironment(TaskListener.NULL)
['JOB_NAME', 'BUILD_NUMBER', 'BRANCH_NAME', 'GIT_COMMIT', 'NODE_NAME'].each { key ->
println "${key}=${env?.get(key)}"
}
EOF
Если у скрипта нет разрешения или плагин изменяет доступные метаданные, вернитесь к консольному логу и конфигурации задания.
Сравните с последней успешной сборкой
Один неудачный лог полезен. Неудачный лог рядом с последним успешным — еще лучше.
Найдите номер последней успешной сборки:
jcli groovy = <<'EOF'
def job = Jenkins.instance.getItemByFullName('MyPipelineJob')
def b = job?.getLastSuccessfulBuild()
println b == null ? 'No successful build found' : b.number
EOF
Затем получите оба лога:
jcli console MyPipelineJob 122 > build-122-success.log
jcli console MyPipelineJob 123 > build-123-failed.log
Сравните команды, версии зависимостей, метки агентов, ветки и SHA-суммы checkout. Многие сбои возникают из-за измененного базового образа, перемещенной зависимости, другого агента или истекших учетных данных между сборками.
Для пайплайнов на основе Git этих значений часто достаточно для начала:
grep -nE "Checking out|GIT_COMMIT|BRANCH_NAME|git rev-parse|Docker|image:" build-123-failed.log
Перезапустите сборку осторожно
Когда вы поняли причину сбоя или применили исправление, запустите новую сборку:
jcli build MyPipelineJob
Для параметризованных заданий:
jcli build MyPipelineJob -p BRANCH=main -p ENVIRONMENT=staging
Чтобы дождаться и вывести результат, проверьте поддерживаемые опции вашего контроллера:
jcli help build
Общие опции включают ожидание завершения и вывод консоли, но названия могут различаться в зависимости от версии Jenkins и плагинов.
Не перезапускайте задания развертывания продакшена просто чтобы посмотреть, что произойдет. Сначала подтвердите параметры, учетные данные и целевую среду. Если задание не идемпотентно, перезапуск может усугубить инцидент.
Используйте вывод CLI в заметках об инциденте
CLI хорош для создания следа. Сохраните точный лог и использованные метаданные:
mkdir -p incident-jenkins-123
jcli console MyPipelineJob 123 > incident-jenkins-123/console.log
jcli get-job MyPipelineJob > incident-jenkins-123/job-config.xml
Относитесь к job-config.xml как к конфиденциальному, если он содержит ссылки на учетные данные, URL или внутренние имена. Не вставляйте его в публичные тикеты.
Компактная заметка об инциденте может включать:
Job: MyPipelineJob #123
Failed stage: Unit tests
First failing command: npm test
Commit: abc1234
Agent: linux-build-07
Likely cause: dependency install used Node 22 instead of expected Node 20
Action: pinned tool version and reran #124 successfully
Это гораздо полезнее, чем "Jenkins failed."
Практический поток устранения неполадок
Используйте этот порядок, когда сборка падает и вам нужен быстрый сигнал:
jcli who-am-i
jcli console MyPipelineJob 123 > build-123.log
grep -niE "error|failed|exception|permission denied|timeout" build-123.log | head -40
grep -n "\[Pipeline\] stage" build-123.log
Затем проверьте параметры и причины с помощью Groovy, сравните с последней успешной сборкой и перезапускайте только после того, как узнаете, был ли сбой в коде, инфраструктуре, учетных данных или входных параметрах.
Jenkins CLI не будет магически диагностировать каждую неудачную сборку. Что он делает хорошо — так это устраняет трение. Он быстро доставляет лог, метаданные и команду перезапуска в ваш терминал, где вы можете искать, сравнивать, сохранять и повторять те же проверки в следующий раз, когда пайплайн сломается.