Come / quando Execute Shell contrassegna una build come errore in Jenkins?


112

Le storie dell'orrore che ho trovato mentre cercavo una risposta per questo ...

OK, ho uno script .sh che praticamente fa tutto ciò che Jenkins dovrebbe fare:

  • controlla le fonti da SVN
  • costruire il progetto
  • distribuisce il progetto
  • pulisce da solo

Quindi in Jenkins devo solo 'costruire' il progetto eseguendo lo script in un comando Execute Shell. Lo script viene eseguito (i sorgenti vengono scaricati, il progetto viene compilato / distribuito) ma poi contrassegna la compilazione come un errore: Il passaggio di compilazione "Esegui shell" contrassegnato come errore Anche se lo script è stato eseguito correttamente! Ho provato a chiudere lo script con:

  • exit 0 (contrassegna ancora come errore)
  • exit 1 (contrassegna come errore, come previsto)
  • nessun comando di uscita (lo contrassegna come errore)

Quando, come e perché Execute Shell contrassegna la mia build come un errore?

Risposte:


131

Per prima cosa, passa il mouse sull'area grigia sottostante. Non fa parte della risposta, ma va assolutamente detto:

Se hai uno script di shell che fa "checkout, build, deploy" tutto da solo, allora perché stai usando Jenkins? Stai rinunciando a tutte le caratteristiche di Jenkins che lo rendono quello che è. Potresti anche fare in modo che un cron o un hook post-commit SVN chiami direttamente lo script. Jenkins che esegue il checkout SVN stesso è fondamentale. Consente alle build di essere attivate solo quando ci sono modifiche (o su timer, o manuale, se preferisci). Tiene traccia delle modifiche tra le build. Mostra tali modifiche, così puoi vedere quale build era per quale set di modifiche. Invia un'e-mail ai committenti quando le loro modifiche hanno causato la compilazione riuscita o non riuscita (di nuovo, come configurato come preferisci). Invierà un'email ai committenti quando le loro correzioni hanno risolto la build in errore. E sempre di più. L'archiviazione degli artefatti da parte di Jenkins li rende inoltre disponibili, per build, direttamente da Jenkins. Sebbene non sia cruciale come il checkout SVN, questo è ancora una volta parte integrante di ciò che lo rende Jenkins. Lo stesso con la distribuzione. A meno che non si disponga di un unico ambiente, la distribuzione di solito avviene in più ambienti. Jenkins può tenere traccia di quale ambiente viene distribuito in una build specifica (con un set specifico di modifiche SVN), attraverso l'uso delle promozioni. Stai rinunciando a tutto questo. Sembra che ti venga detto "devi usare Jenkins" ma non lo vuoi veramente, e lo stai facendo solo per toglierti di dosso i tuoi capi, solo per mettere un segno di spunta "sì, ho usato Jenkins"

La risposta breve è: il codice di uscita dell'ultimo comando della Jenkin è Esegui Shell passaggio di generazione è ciò che determina il successo / insuccesso del costruire passo dopo . 0- successo, anything else- fallimento. Nota, questo determina il successo / fallimento della fase di costruzione , non dell'intero lavoro eseguito . Il successo / fallimento dell'intero lavoro può essere ulteriormente influenzato da più passaggi di compilazione e da azioni e plug-in post-compilazione.

Hai menzionato Build step 'Execute shell' marked build as failure, quindi ci concentreremo solo su un singolo passaggio di costruzione. Se la tua fase di compilazione Execute shell ha solo una singola riga che chiama il tuo script di shell, il codice di uscita del tuo script di shell determinerà il successo / fallimento della fase di build. Se hai più righe, dopo l'esecuzione dello script di shell, esaminale attentamente, poiché sono quelle che potrebbero causare errori.

Infine, leggi qui Jenkins Build Script esce dopo l'esecuzione di Google Test . Non è direttamente correlato alla tua domanda, ma nota quella parte relativa al lancio di Jenkins nella fase di compilazione Esegui Shell , come script di shell con/bin/sh -xe

I -emezzi che lo script shell uscire con il fallimento, anche se solo 1 comando non riesce, anche se si fa il controllo degli errori per questo comando (perché lo script si chiude prima che arrivi al tuo controllo degli errori). Ciò è contrario alla normale esecuzione degli script di shell, che di solito stampano il messaggio di errore per il comando fallito (o lo reindirizzano a null e lo gestiscono con altri mezzi), e continuano.

Per aggirare questo problema, aggiungi set +eall'inizio del tuo script di shell.

Dal momento che dici che il tuo script fa tutto ciò che dovrebbe fare, è probabile che il comando fallito sia da qualche parte alla fine dello script. Forse un'eco finale? O una copia di artefatti da qualche parte? Senza vedere l'output completo della console, stiamo solo supponendo.

Si prega di inviare l'output della console di esecuzione del lavoro, e preferibilmente anche lo stesso script di shell, e quindi potremmo dirvi esattamente quale riga sta fallendo.


6
Il motivo per cui uso ancora Jenkins non mi è chiaro ... Sembra che qualcuno al vertice non abbia capito bene che abbiamo già questo script e abbia insistito perché usassimo Jenkins. Mi sento come se fossi in una striscia di Dilbert. Grazie per il suggerimento. Ha risolto il problema
tester

45
Ci sono ancora buone ragioni per usare Jenkins: l'audit trail, la visibilità dello stato di compilazione, ecc. Se si dispone già di uno script di compilazione, spostarlo in Jenkins è un buon primo passo prima del refactoring per sfruttare le funzionalità di Jenkins.
aehlke

3
Il collegamento incrociato di questa risposta serverfault.com/a/143576/186454 set + e e set -e può essere specificato ovunque nello script. Qualsiasi codice intermedio non fallirà la compilazione se il valore restituito non è 0.
Alex Skrypnyk

2
molto ben detto sul set di shell script vs jenkins
pushya

usiamo jenkins per fornire accesso autenticato e un'interfaccia utente per il lavoro. Un cron non lo taglierebbe. Jenkins non esegue solo script.
ffghfgh

90

La risposta semplice e breve alla tua domanda è

Si prega di aggiungere la seguente riga nella fase di compilazione "Esegui shell".

#!/bin/sh

Ora lascia che ti spieghi il motivo per cui abbiamo bisogno di questa riga per il lavoro di compilazione "Execute Shell".

Per impostazione predefinita, Jenkins accetta /bin/sh -xee questo significa -xche stamperà ogni singolo -ecomando e l'altra opzione , che fa sì che la shell interrompa immediatamente l'esecuzione di uno script quando un comando termina con un codice di uscita diverso da zero (quando un comando fallisce).

Quindi aggiungendo il #!/bin/shti permetterà di eseguire senza opzioni.


4
Upvoted. Non conoscevo l'impostazione predefinita -xe. Quando il mio comando grep non ha trovato una stringa, l'intero script non è riuscito perché grep ha restituito un valore di ritorno diverso da 0 :)
Somaiah Kumbera

Ha funzionato alla grande! Usandolo sul mio dei passaggi non cruciali, un passaggio di pulizia che fa semplicemente qualcosa di simile find . -name 'bower_components' -exec rm {} \;e in alcuni casi non ha funzionato. Grazie!
yorch

questo ha cancellato tutto - "E l'altra opzione -e, che fa sì che la shell interrompa immediatamente l'esecuzione di uno script quando un comando termina con un codice di uscita diverso da zero (quando qualsiasi comando fallisce)."
Paramvir Singh Karwal

3

A mio parere, disattivare l' -eopzione per la shell è una pessima idea. Alla fine uno dei comandi nello script fallirà a causa di condizioni transitorie come spazio su disco insufficiente o errori di rete. Senza -eJenkins non se ne accorgerà e continuerà felicemente. Se Jenkins è configurato per eseguire la distribuzione, ciò potrebbe comportare il push di codice errato e l'arresto del sito.

Se nel tuo script è presente una riga in cui è previsto un errore, come grep o find, aggiungila || truealla fine di quella riga. Ciò garantisce che la linea restituirà sempre il successo.

Se è necessario utilizzare quel codice di uscita, è possibile caricare il comando nell'istruzione if:

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

Oppure puoi acquisire il codice di ritorno nella tua ||clausola:

grep foo bar || ret=$?

1
Grazie Bryan. Mi hai salvato la giornata. Inoltre, penso che sia una buona idea attivare sia -x che -e. Così che vedi nel tuo registro di jenkins.
Bikal Basnet

2

Chiaro e semplice:

Se Jenkins vede la fase di compilazione (che è anche uno script) termina con un codice diverso da zero, la compilazione è contrassegnata da una pallina rossa (= non riuscita).

Perché esattamente ciò accade dipende dallo script di build.

Ho scritto qualcosa di simile da un altro punto di vista, ma forse sarà utile leggerlo comunque: perché Jenkins pensa che la mia build sia riuscita?


0

Quindi aggiungendo il file #!/bin/shti permetterà di eseguire senza opzioni.

Mi ha anche aiutato a risolvere un problema in cui stavo eseguendo lo script bash dal master Jenkins sul mio slave Linux. Aggiungendo semplicemente #!/bin/bashsopra il mio script effettivo nel blocco "Esegui shell", ho risolto il problema poiché altrimenti veniva eseguita la versione fornita da git di Windows della shell bash che dava un errore.


0

In Jenkins ver. 1.635, è impossibile mostrare una variabile d'ambiente nativa come questa:

$BUILD_NUMBER or ${BUILD_NUMBER}

In questo caso, devi impostarlo in un'altra variabile.

set BUILDNO = $BUILD_NUMBER
$BUILDNO
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.