Risoluzione rapida dei build falliti utilizzando la CLI di Jenkins

Usa la CLI di Jenkins per ispezionare build falliti, visualizzare i log, controllare i parametri e rieseguire i job senza navigare nell'interfaccia utente.

Risoluzione rapida dei build falliti utilizzando la CLI di Jenkins

L'interfaccia web di Jenkins è utile quando stai esplorando. La CLI di Jenkins è migliore quando conosci già il nome del job, hai bisogno del log immediatamente o vuoi ripetere gli stessi controlli senza cliccare tra le pagine.

Un build fallito di solito richiede tre informazioni: cosa è stato eseguito, dove è fallito e cosa è cambiato rispetto all'ultima esecuzione riuscita. La CLI può ottenere tutte e tre rapidamente se la configuri una volta.

Configura un comando CLI ripetibile

Scarica il jar della CLI dal tuo controller Jenkins:

curl -O "$JENKINS_URL/jnlpJars/jenkins-cli.jar"

Usa un token API, non la password del tuo account:

export JENKINS_URL="https://jenkins.example.com"
export JENKINS_USER="tuo-utente"
export JENKINS_API_TOKEN="tuo-token-api"

alias jcli='java -jar jenkins-cli.jar -s "$JENKINS_URL" -auth "$JENKINS_USER:$JENKINS_API_TOKEN"'

Testa l'autenticazione prima di risolvere un vero fallimento:

jcli who-am-i
jcli help

Se questo fallisce, risolvi prima l'accesso alla CLI. Le cause comuni sono un URL errato, un token copiato con uno spazio extra, permessi mancanti o un'impostazione di sicurezza di Jenkins che disabilita il trasporto CLI che stai cercando di utilizzare.

Per script condivisi, evita alias di shell. Avvolgi il comando in un piccolo script o usa variabili d'ambiente nel tuo archivio segreto CI in modo che i token non finiscano nella cronologia della shell.

Trova il build fallito

Se conosci il nome del job e il numero del build, vai direttamente al log della console. Se sai solo che qualcosa è fallito di recente, inizia con Groovy tramite la 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

Per cartelle e pipeline multibranch, usa il nome completo del job esattamente come Jenkins lo conosce. Un job di un ramo potrebbe assomigliare a:

team-service/main
team-service/PR-42
cartella-a/cartella-b/deploy-prod

Se un nome contiene spazi, racchiudilo tra virgolette nella tua shell:

jcli console "Cartella Con Spazi/Mia Pipeline" 128

Ottieni prima il log della console

Il log della console è ancora la fonte di verità più veloce per la maggior parte dei fallimenti:

jcli console MyPipelineJob 123

Per log lunghi, salva una copia e cerca con contesto:

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

Non affidarti solo alla prima riga che contiene "error". Gli strumenti di build spesso stampano avvisi, nomi di test o testo di fallimento previsto. Cerca il primo fallimento significativo dopo l'inizio dello stage, poi leggi le righe precedenti. La causa è spesso sopra lo stack trace.

Per un build in esecuzione, segui il log:

jcli console MyPipelineJob 123 -f

Alcune versioni di Jenkins e modalità CLI accettano --follow; altre usano -f. Controlla jcli help console sul tuo controller.

Identifica lo stage che è fallito

I log delle pipeline includono marcatori di stage. Cercali vicino al fallimento:

grep -n "\[Pipeline\] stage" build-123.log

Poi ispeziona la sezione dopo l'ultimo marcatore di stage prima dell'errore. Se il log è rumoroso, aprilo con less:

less build-123.log

All'interno di less, cerca /ERROR, /Exception o /[Pipeline] stage.

Un buon Jenkinsfile rende tutto più semplice stampando nomi di step chiari prima di operazioni rischiose:

echo 'Installazione dipendenze npm'
sh 'npm ci'
echo 'Esecuzione test unitari'
sh 'npm test'

Se ogni step è solo sh './ci.sh', la CLI può comunque recuperare il log, ma il log potrebbe non dirti abbastanza. In tal caso, migliora la pipeline dopo l'incidente.

Controlla parametri e cause

Un build può fallire perché è stato eseguito con il ramo sbagliato, l'ambiente sbagliato o un parametro obsoleto. Recupera i metadati del build con Groovy:

jcli groovy = <<'EOF'
def job = Jenkins.instance.getItemByFullName('MyPipelineJob')
def build = job?.getBuildByNumber(123)
if (build == null) {
  println 'Build non trovato'
  return
}
println "Job: ${job.fullName}"
println "Build: #${build.number}"
println "Risultato: ${build.result}"
println "Durata: ${build.durationString}"
println 'Cause:'
build.getCauses().each { println "- ${it.shortDescription}" }
println 'Parametri:'
build.getAction(hudson.model.ParametersAction)?.parameters?.each {
  println "- ${it.name}=${it.value}"
}
EOF

Questo è particolarmente utile per job di deployment. Un deployment di produzione fallito con BRANCH=feature/test è un problema molto diverso da un deployment fallito del tag di rilascio previsto.

Fai attenzione a stampare le variabili d'ambiente. Potrebbero includere segreti. Se hai bisogno di dettagli sull'ambiente, stampa chiavi sicure specifiche invece di scaricare tutto:

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

Se al tuo script mancano permessi o un plugin cambia i metadati disponibili, torna al log della console e alla configurazione del job.

Confronta con l'ultimo build riuscito

Un singolo log fallito è utile. Un log fallito accanto all'ultimo log riuscito è meglio.

Trova il numero dell'ultimo build riuscito:

jcli groovy = <<'EOF'
def job = Jenkins.instance.getItemByFullName('MyPipelineJob')
def b = job?.getLastSuccessfulBuild()
println b == null ? 'Nessun build riuscito trovato' : b.number
EOF

Poi recupera entrambi i log:

jcli console MyPipelineJob 122 > build-122-successo.log
jcli console MyPipelineJob 123 > build-123-fallito.log

Confronta i comandi, le versioni delle dipendenze, le etichette degli agenti, i rami e gli SHA del checkout. Molti fallimenti derivano da un'immagine di base cambiata, una dipendenza spostata, un agente diverso o una credenziale scaduta tra i build.

Per pipeline basate su Git, questi valori sono spesso sufficienti per iniziare:

grep -nE "Checking out|GIT_COMMIT|BRANCH_NAME|git rev-parse|Docker|image:" build-123-fallito.log

Riesegui un build con attenzione

Una volta compreso il fallimento o applicata una correzione, attiva un nuovo build:

jcli build MyPipelineJob

Per job parametrizzati:

jcli build MyPipelineJob -p BRANCH=main -p ENVIRONMENT=staging

Per attendere e trasmettere l'output, controlla le opzioni supportate dal tuo controller:

jcli help build

Le opzioni comuni includono l'attesa del completamento e la stampa dell'output della console, ma i nomi possono variare in base alla versione di Jenkins e ai plugin.

Non rieseguire job di deployment di produzione solo per vedere cosa succede. Conferma prima parametri, credenziali e ambiente di destinazione. Se il job non è idempotente, una riesecuzione può peggiorare l'incidente.

Usa l'output della CLI nelle note dell'incidente

La CLI è utile per lasciare una traccia. Salva il log esatto e i metadati che hai utilizzato:

mkdir -p incidente-jenkins-123
jcli console MyPipelineJob 123 > incidente-jenkins-123/console.log
jcli get-job MyPipelineJob > incidente-jenkins-123/job-config.xml

Tratta job-config.xml come sensibile se contiene riferimenti a credenziali, URL o nomi interni. Non incollarlo in ticket pubblici.

Una nota di incidente compatta potrebbe includere:

Job: MyPipelineJob #123
Stage fallito: Test unitari
Primo comando fallito: npm test
Commit: abc1234
Agente: linux-build-07
Causa probabile: installazione dipendenze ha usato Node 22 invece del previsto Node 20
Azione: versione dello strumento bloccata e rieseguito #124 con successo

Questo è molto più utile di "Jenkins fallito."

Un flusso pratico di risoluzione dei problemi

Usa questo ordine quando un build fallisce e hai bisogno di segnali rapidamente:

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

Poi ispeziona parametri e cause con Groovy, confronta con l'ultimo build riuscito e riesegui solo dopo aver capito se il fallimento era dovuto a codice, infrastruttura, credenziali o parametri di input.

La CLI di Jenkins non diagnosticherà magicamente ogni build fallito. Ciò che fa bene è rimuovere l'attrito. Porta il log, i metadati e il comando di riesecuzione nel tuo terminale rapidamente, dove puoi cercare, confrontare, salvare e ripetere gli stessi controlli la prossima volta che una pipeline si rompe.