Comment / Quand Execute Shell marque-t-il une compilation comme un échec dans Jenkins?

112

Les histoires d'horreur que j'ai trouvées en cherchant une réponse à celle-ci ...

OK, j'ai un script .sh qui fait à peu près tout ce que Jenkins est censé faire:

  • vérifie les sources de SVN
  • construire le projet
  • déploie le projet
  • nettoie après lui-même

Donc, dans Jenkins, je n'ai qu'à «construire» le projet en exécutant le script dans une commande Execute Shell. Le script est exécuté (les sources sont téléchargées, le projet est construit / déployé) mais ensuite il marque la construction comme un échec: Étape de construction «Exécuter le shell» marquée comme un échec Même si le script a été exécuté avec succès! J'ai essayé de fermer le script avec:

  • exit 0 (le marque toujours comme un échec)
  • exit 1 (le marque comme un échec, comme prévu)
  • aucune commande de sortie du tout (le marque comme un échec)

Quand, comment et pourquoi Execute Shell marque-t-il ma construction comme un échec?

testeur
la source

Réponses:

131

Tout d'abord, passez la souris sur la zone grise ci-dessous. Cela ne fait pas partie de la réponse, mais il faut absolument le dire:

Si vous avez un script shell qui "checkout, build, deploy" tout seul, alors pourquoi utilisez-vous Jenkins? Vous renoncez à toutes les fonctionnalités de Jenkins qui en font ce qu'il est. Vous pourriez aussi bien avoir un cron ou un hook post-commit SVN appeler le script directement. Jenkins effectue la vérification SVN elle-même est cruciale. Il permet aux builds d'être déclenchés uniquement lorsqu'il y a des changements (ou sur minuterie, ou manuel, si vous préférez). Il garde une trace des changements entre les versions. Il montre ces changements, afin que vous puissiez voir quelle version était pour quel ensemble de modifications. Il envoie un e-mail aux commetteurs lorsque leurs modifications ont entraîné une compilation réussie ou échouée (encore une fois, selon la configuration que vous préférez). Il enverra un e-mail aux commetteurs lorsque leurs correctifs auront corrigé la version défaillante. Et de plus en plus. Jenkins archivant les artefacts les rend également disponibles, par build, directement à partir de Jenkins. Bien que ce ne soit pas aussi crucial que le paiement SVN, cela fait à nouveau partie intégrante de ce qui en fait Jenkins. Idem pour le déploiement. À moins que vous n'ayez un seul environnement, le déploiement se produit généralement dans plusieurs environnements. Jenkins peut garder une trace de l'environnement dans lequel une version spécifique (avec un ensemble spécifique de modifications SVN) est déployée, grâce à l'utilisation de Promotions. Vous renoncez à tout cela. On dirait qu'on vous dit "vous devez utiliser Jenkins" mais vous ne le voulez pas vraiment, et vous le faites juste pour vous faire perdre vos patrons, juste pour mettre une coche "oui, j'ai utilisé Jenkins"

La réponse courte est: le code de sortie de la dernière commande de l' étape de construction de Jenkin's Execute Shell est ce qui détermine le succès / échec de l' étape de construction . 0- succès, anything else- échec. Notez que cela détermine le succès / l'échec de l' étape de construction , pas l'ensemble du travail exécuté . Le succès / l'échec de l'ensemble de l'exécution du travail peut en outre être affecté par plusieurs étapes de construction, ainsi que par des actions et des plugins post-construction.

Vous l'avez mentionné Build step 'Execute shell' marked build as failure, nous nous concentrerons donc sur une seule étape de construction. Si votre étape de construction Execute shell n'a qu'une seule ligne qui appelle votre script shell, alors le code de sortie de votre script shell déterminera le succès / l'échec de l'étape de construction. Si vous avez plus de lignes, après exécution de votre script shell, examinez-les attentivement, car ce sont elles qui pourraient causer des échecs.

Enfin, lisez ici Jenkins Build Script se termine après l'exécution de Google Test . Ce n'est pas directement lié à votre question, mais notez que la partie concernant le lancement par Jenkins de l' étape de construction Execute Shell , en tant que script shell avec/bin/sh -xe

Les -emoyens que le script shell va sortir à l' échec, même si seulement 1 commande échoue, même si vous faites la vérification des erreurs pour cette commande (car les sorties de script avant qu'il arrive à votre vérification d'erreur). Ceci est contraire à l'exécution normale des scripts shell, qui affichent généralement le message d'erreur de la commande ayant échoué (ou le redirigent vers null et le traitent par d'autres moyens), et continuez.

Pour contourner cela, ajoutez set +een haut de votre script shell.

Puisque vous dites que votre script fait tout ce qu'il est censé faire, il est probable que la commande défaillante se trouve quelque part à la fin du script. Peut-être un écho final? Ou une copie d'artefacts quelque part? Sans voir la sortie complète de la console, nous ne faisons que deviner.

Veuillez publier la sortie de la console de l'exécution du travail, et de préférence le script shell lui-même, et nous pourrons alors vous dire exactement quelle ligne échoue.

slave
la source
6
La raison pour laquelle j'utilise toujours Jenkins n'est pas claire pour moi ... Il semble que quelqu'un au sommet n'a pas tout à fait compris que nous avons déjà ce script et a insisté pour que nous utilisions Jenkins. J'ai l'impression d'être dans un strip Dilbert. Merci pour le conseil -e. Il a résolu le problème
testeur
45
Il y a encore de bonnes raisons d'utiliser Jenkins: la piste d'audit, la visibilité de l'état de la construction, etc. Si vous avez déjà un script de construction, le déplacer vers Jenkins est une bonne première étape avant de le refactoriser pour profiter des fonctionnalités de Jenkins.
aehlke
3
La liaison croisée de cette réponse serverfault.com/a/143576/186454 set + e et set -e peut être spécifiée n'importe où dans votre script. Tout code intermédiaire n'échouera pas à la construction si la valeur renvoyée n'est pas 0.
Alex Skrypnyk
2
très bien dit sur le script shell vs set
jenkins
nous utilisons jenkins pour fournir un accès authentifié et une interface utilisateur pour le travail. Un cron ne le couperait pas. Jenkins ne fait pas que lancer des cripts.
ffghfgh
90

La réponse simple et courte à votre question est

Veuillez ajouter la ligne suivante dans votre étape de construction "Exécuter le shell".

#!/bin/sh

Maintenant, laissez-moi vous expliquer la raison pour laquelle nous avons besoin de cette ligne pour le travail de compilation "Execute Shell".

Par défaut, Jenkins prend /bin/sh -xeet ce moyen -xaffichera chaque commande, et l'autre option -e, qui fait que le shell arrête immédiatement d'exécuter un script lorsqu'une commande se termine avec un code de sortie différent de zéro (lorsqu'une commande échoue).

Donc, en ajoutant le #!/bin/shvous permettra d'exécuter sans option.

Abhijeet Kamble
la source
4
J'ai voté pour. Je ne connaissais pas la valeur par défaut -xe. Lorsque ma comman grep ne trouvait pas de chaîne, tout mon script a échoué car grep a renvoyé une valeur de retour non 0 :)
Somaiah Kumbera
A très bien fonctionné! En l'utilisant sur mes étapes non cruciales, une étape de nettoyage qui fait juste quelque chose comme find . -name 'bower_components' -exec rm {} \;et dans certains cas, cela a échoué. Merci!
yorch
cela a tout effacé - 'Et l'autre option -e, qui fait que le shell arrête immédiatement d'exécuter un script lorsqu'une commande se termine avec un code de sortie différent de zéro (lorsqu'une commande échoue).'
Paramvir Singh Karwal
3

À mon avis, désactiver l' -eoption de votre shell est une très mauvaise idée. Finalement, l'une des commandes de votre script échouera en raison de conditions transitoires telles que l'espace disque insuffisant ou des erreurs réseau. Sans -eJenkins ne le remarquera pas et continuera avec bonheur. Si Jenkins est configuré pour effectuer le déploiement, cela peut entraîner un code incorrect et la mise hors service de votre site.

Si vous avez une ligne dans votre script où un échec est attendu, comme un grep ou une recherche, ajoutez simplement || trueà la fin de cette ligne. Cela garantit que la ligne renverra toujours le succès.

Si vous devez utiliser ce code de sortie, vous pouvez soit hisser la commande dans votre instruction if:

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

Ou vous pouvez capturer le code de retour dans votre ||clause:

grep foo bar || ret=$?
Bryan Larsen
la source
1
Merci Bryan. Tu as sauvé ma journée. De plus, je pense que c'est une bonne idée d'activer à la fois -x et -e. Pour que vous voyiez dans votre journal jenkins.
Bikal Basnet
2

Clair et simple:

Si Jenkins voit que l'étape de construction (qui est également un script) se termine avec un code différent de zéro, la construction est marquée d'une boule rouge (= échec).

Pourquoi exactement cela se produit dépend de votre script de construction.

J'ai écrit quelque chose de similaire d'un autre point de vue, mais peut-être que cela aidera quand même à le lire: Pourquoi Jenkins pense-t-il que ma construction a réussi?

sti
la source
0

Donc, en ajoutant le #!/bin/shvous permettra d'exécuter sans option.

Cela m'a également aidé à résoudre un problème où j'exécutais un script bash du maître Jenkins sur mon esclave Linux. En ajoutant juste #!/bin/bashau-dessus de mon script réel dans le bloc "Execute Shell", cela a résolu mon problème, sinon il exécutait la version Windows fournie par git de bash shell qui donnait une erreur.

Shailender Singh
la source
0

Dans Jenkins ver. 1.635, il est impossible d'afficher une variable d'environnement native comme celle-ci:

$BUILD_NUMBER or ${BUILD_NUMBER}

Dans ce cas, vous devez le définir dans une autre variable.

set BUILDNO = $BUILD_NUMBER
$BUILDNO
user10413452
la source