web-dev-qa-db-fra.com

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

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 était censé faire:

  • vérifie les sources de SVN
  • construire le projet
  • déploie le projet
  • nettoie après

Donc, dans Jenkins, je n'ai qu'à "construire" le projet en exécutant le script dans une commande d'exécution de shell . Le script est exécuté (les sources sont téléchargées, le projet est construit/déployé), mais il est ensuite marqué comme étant un échec. ! J'ai essayé de fermer le script avec:

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

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

101
tester

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 "extrait, construit, déploie" tout seul, 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 SVN post-commit appeler directement le script. Jenkins effectuer le contrôle SVN lui-même est crucial. Cela permet aux générations d'être déclenchées seulement quand il y a des changements (ou sur la minuterie, ou manuellement, si vous préférez). Il garde une trace des changements entre les générations. Il montre ces modifications afin que vous puissiez voir quelle version était destinée à quel ensemble de modifications. Il envoie un e-mail aux committers lorsque leurs modifications entraînent une génération réussie ou échouée (à nouveau, selon la configuration souhaitée). Il enverra un e-mail aux committers lorsque leurs correctifs auront corrigé la construction défaillante. Et de plus en plus. Jenkins archiver les artefacts les rend également disponibles, par build, directement à partir de Jenkins. Bien que cela ne soit pas aussi crucial que la caisse SVN, ceci fait à nouveau partie intégrante de ce qui fait de Jenkins. Même avec le déploiement. À moins que vous n'ayez un seul environnement, le déploiement a généralement lieu dans plusieurs environnements. Jenkins peut garder trace de l'environnement dans lequel une construction spécifique (avec un ensemble spécifique de modifications SVN) est déployée, via l'utilisation de Promotions. Vous renoncez à tout cela. On dirait qu'on vous dit "vous devez utiliser Jenkins" mais vous ne voulez pas vraiment, et vous le faites juste pour mettre vos patrons sur le dos, juste pour cocher "oui, j'ai utilisé Jenkins"

La réponse courte est la suivante: le code de sortie de la commande last de l’étape de construction Execute Shell de Jenkin est ce qui détermine le succès/échec de l’étape Build. 0 - succès, anything else - échec . Notez que ceci détermine le succès/l'échec de l'étape build, pas de l'ensemble exécution du travail _. Le succès/l'échec de l'exécution du travail entier peut encore être affecté par plusieurs étapes de construction, actions et plugins post-génération.

Vous avez mentionné Build step 'Execute Shell' marked build as failure, nous allons donc nous concentrer sur une seule étape de construction. Si votre étape de construction Execute Shell ne comporte qu'une seule ligne appelant votre script Shell, 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 l'exécution de votre script Shell, examinez-les attentivement, car ce sont elles qui risquent de provoquer un échec.

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

Le -e signifie que le script shell va quitter en cas d'échec, même si une seule commande échoue, même si vous effectuez une vérification d'erreur pour cette commande (car le script se ferme avant la 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 gèrent par un autre moyen) et continuent.

Pour contourner ce problème, ajoutez set +e en 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 en échec 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 devinons.

Veuillez poster la sortie de la console du travail exécuté, et de préférence le script Shell lui-même, pour que nous puissions vous dire exactement quelle ligne échoue.

119
Slav

La réponse simple et courte à votre question est

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

#!/bin/sh

Laissez-moi maintenant vous expliquer la raison pour laquelle nous avons besoin de cette ligne pour le travail de construction "Exécuter Shell".

Par défaut, Jenkins prend /bin/sh -xe et cela signifie que -x imprimera chaque commande. Et l'autre option -e, qui obligera Shell à arrêter l'exécution d'un script immédiatement lorsqu'une commande se ferme avec un code de sortie différent de zéro (si une commande échoue). 

Donc, en ajoutant le #!/bin/sh vous permettra d’exécuter sans option.

80
Abhijeet Kamble

Clair et simple:

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

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 qu'il sera utile de le lire quand même: Pourquoi Jenkins pense-t-il que ma construction a réussi?

2
sti

À mon avis, désactiver l'option -e sur votre Shell est une très mauvaise idée. En fin de compte, 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 -e, Jenkins ne le remarquera pas et continuera joyeusement. Si Jenkins est configuré pour effectuer le déploiement, des codes défectueux risquent de vous pousser et de détruire 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 cette ligne retournera 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=$?
2
Bryan Larsen

Donc, en ajoutant le #!/bin/sh vous permettra d’exécuter sans option.

Cela m'a également aidé à résoudre un problème où j'exécutais le script bash à partir du maître Jenkins sur mon esclave Linux. En ajoutant simplement #!/bin/bash au-dessus de mon script actuel dans "Execute Shell", vous avez résolu le problème. Sinon, il exécutait une version fournie par Windows de bash Shell qui fournissait une erreur.

0
shailender chauhan

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

$ BUILD_NUMBER ou $ {BUILD_NUMBER}

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

set BUILDNO = $ BUILD_NUMBER $ BUILDNO

0
user10413452