Jenkins CLI를 사용한 실패한 빌드 빠른 문제 해결
Jenkins CLI를 사용하여 UI를 탐색하지 않고 실패한 빌드를 검사하고, 로그를 스트리밍하며, 매개변수를 확인하고, 작업을 재실행합니다.
Jenkins CLI를 사용한 실패한 빌드 빠른 문제 해결
Jenkins 웹 UI는 탐색할 때 유용합니다. Jenkins CLI는 작업 이름을 이미 알고 있거나, 지금 당장 로그가 필요하거나, 페이지를 클릭하지 않고 동일한 확인을 반복하려는 경우에 더 좋습니다.
실패한 빌드는 일반적으로 세 가지 정보가 필요합니다: 무엇이 실행되었는지, 어디서 실패했는지, 마지막 성공 이후 무엇이 변경되었는지입니다. CLI는 한 번 설정하면 이 세 가지를 모두 빠르게 가져올 수 있습니다.
반복 가능한 CLI 명령 설정
자신의 Jenkins 컨트롤러에서 CLI jar를 다운로드하세요:
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, 추가 공백이 포함된 토큰, 누락된 권한, 또는 사용하려는 CLI 전송을 비활성화하는 Jenkins 보안 설정입니다.
공유 스크립트의 경우 셸 별칭을 피하세요. 명령을 작은 스크립트로 감싸거나 CI 비밀 저장소에서 환경 변수를 사용하여 토큰이 셸 기록에 남지 않도록 하세요.
실패한 빌드 찾기
작업 이름과 빌드 번호를 알고 있다면 콘솔 로그로 바로 건너뛰세요. 최근에 무언가 실패했다는 것만 알고 있다면 CLI를 통해 Groovy로 시작하세요:
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를 비교하세요. 많은 실패는 변경된 기본 이미지, 이동된 종속성, 다른 에이전트 또는 빌드 사이에 만료된 자격 증명에서 비롯됩니다.
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는 모든 실패한 빌드를 마술처럼 진단하지는 않습니다. CLI가 잘하는 것은 마찰을 제거하는 것입니다. 로그, 메타데이터 및 재실행 명령을 터미널로 신속하게 가져와서 파이프라인이 중단될 때마다 검색, 비교, 저장 및 동일한 확인을 반복할 수 있게 해줍니다.