Wie / wann markiert Execute Shell einen Build in Jenkins als Fehler?

112

Die Horrorgeschichten, die ich gefunden habe, als ich nach einer Antwort auf diese Frage gesucht habe ...

OK, ich habe ein .sh-Skript, das so ziemlich alles macht, was Jenkins tun soll:

  • checkt Quellen von SVN aus
  • Baue das Projekt
  • stellt das Projekt bereit
  • reinigt nach sich selbst

In Jenkins muss ich das Projekt nur erstellen, indem ich das Skript in einem Execute Shell-Befehl ausführe. Das Skript wird ausgeführt (die Quellen werden heruntergeladen, das Projekt wird erstellt / bereitgestellt), aber dann wird der Build als Fehler markiert: Build-Schritt 'Shell ausführen' markiert Build als Fehler Auch wenn das Skript erfolgreich ausgeführt wurde! Ich habe versucht, das Skript zu schließen mit:

  • Beenden Sie 0 (markiert es immer noch als Fehler)
  • Beenden Sie 1 (markiert es wie erwartet als Fehler)
  • überhaupt kein Exit-Befehl (markiert ihn als Fehler)

Wann, wie und warum markiert Execute Shell meinen Build als Fehler?

Prüfer
quelle

Antworten:

130

Bewegen Sie zuerst die Maus über den grauen Bereich darunter. Nicht Teil der Antwort, muss aber unbedingt gesagt werden:

Wenn Sie ein Shell-Skript haben, das "Auschecken, Erstellen, Bereitstellen" von selbst ausführt, warum verwenden Sie dann Jenkins? Sie verzichten auf alle Funktionen von Jenkins, die es zu dem machen, was es ist. Sie können das Skript auch direkt von einem Cron oder einem SVN-Post-Commit-Hook direkt aufrufen lassen. Jenkins, der die SVN-Prüfung selbst durchführt, ist von entscheidender Bedeutung. Es ermöglicht, dass die Builds nur ausgelöst werden, wenn Änderungen vorgenommen werden (oder auf Timer oder manuell, wenn Sie dies bevorzugen). Es verfolgt Änderungen zwischen Builds. Es zeigt diese Änderungen an, sodass Sie sehen können, welcher Build für welche Änderungen verwendet wurde. Es sendet Committer per E-Mail, wenn ihre Änderungen zu einem erfolgreichen oder fehlgeschlagenen Build geführt haben (wieder so konfiguriert, wie Sie es bevorzugen). Committer werden per E-Mail benachrichtigt, wenn ihre Fixes den fehlerhaften Build behoben haben. Und immer mehr. Jenkins, der die Artefakte archiviert, stellt sie auch pro Build direkt von Jenkins zur Verfügung. Dies ist zwar nicht so wichtig wie die SVN-Kaufabwicklung, aber es ist wieder ein wesentlicher Bestandteil dessen, was es zu Jenkins macht. Gleiches gilt für die Bereitstellung. Sofern Sie nicht über eine einzige Umgebung verfügen, erfolgt die Bereitstellung normalerweise in mehreren Umgebungen. Jenkins kann mithilfe von Promotions verfolgen, in welcher Umgebung ein bestimmter Build (mit bestimmten SVN-Änderungen) bereitgestellt wird. Sie verzichten auf all das. Es hört sich so an, als würde Ihnen gesagt, "Sie müssen Jenkins verwenden", aber Sie wollen es nicht wirklich, und Sie tun es nur, um Ihre Chefs von Ihrem Rücken zu bekommen, nur um ein Häkchen zu setzen: "Ja, ich habe Jenkins verwendet".

Die kurze Antwort lautet: Der Exit-Code des letzten Befehls des Build-Schritts Execute Shell von Jenkin bestimmt den Erfolg / Misserfolg des Build- Schritts . 0- Erfolg, anything else- Misserfolg. Beachten Sie, dass dies den Erfolg / Misserfolg des Erstellungsschritts bestimmt , nicht den gesamten Joblauf . Der Erfolg / Misserfolg des gesamten Joblaufs kann ferner durch mehrere Erstellungsschritte sowie Aktionen und Plugins nach dem Erstellen beeinflusst werden.

Sie haben es erwähnt Build step 'Execute shell' marked build as failure, daher konzentrieren wir uns nur auf einen einzelnen Build-Schritt. Wenn Ihr Shell- Build-Schritt " Ausführen" nur eine einzige Zeile enthält, die Ihr Shell-Skript aufruft, bestimmt der Exit-Code Ihres Shell-Skripts den Erfolg / Misserfolg des Build-Schritts. Wenn Sie nach der Ausführung Ihres Shell-Skripts mehr Zeilen haben, überprüfen Sie diese sorgfältig, da diese Fehler verursachen können.

Lesen Sie zum Schluss hier, dass Jenkins Build Script nach der Ausführung von Google Test beendet wird . Es hängt nicht direkt mit Ihrer Frage zusammen, aber beachten Sie den Teil über Jenkins, der den Build-Schritt " Shell ausführen" als Shell-Skript mit startet/bin/sh -xe

Die -ebedeutet , dass der Shell - Skript wird verlassen mit dem Scheitern, wenn auch nur einen Befehl fehlschlägt, auch wenn Sie für diesen Befehl Fehlerüberprüfung zu tun (weil das Script beendet , bevor es wird auf Ihre Fehlerprüfung). Dies steht im Gegensatz zur normalen Ausführung von Shell-Skripten, die normalerweise die Fehlermeldung für den fehlgeschlagenen Befehl drucken (oder auf null umleiten und auf andere Weise verarbeiten) und fortfahren.

Um dies zu umgehen, fügen Sie set +eoben in Ihrem Shell-Skript hinzu.

Da Sie sagen, dass Ihr Skript alles tut, was es tun soll, befindet sich der fehlgeschlagene Befehl wahrscheinlich irgendwo am Ende des Skripts. Vielleicht ein letztes Echo? Oder irgendwo eine Kopie von Artefakten? Ohne die vollständige Konsolenausgabe zu sehen, raten wir nur.

Bitte posten Sie die Konsolenausgabe des Joblaufs und vorzugsweise auch das Shell-Skript selbst. Dann können wir Ihnen genau sagen, welche Zeile fehlschlägt.

Slawisch
quelle
6
Der Grund, warum ich immer noch Jenkins benutze, ist mir unklar ... Es scheint, dass jemand an der Spitze nicht ganz verstanden hat, dass wir dieses Skript bereits haben und darauf bestanden, dass wir Jenkins verwenden. Ich fühle mich wie in einem Dilbert-Streifen. Danke für den -e Tipp. Es löste das Problem
Tester
45
Es gibt immer noch gute Gründe, Jenkins zu verwenden: den Audit-Trail, die Sichtbarkeit des Build-Status usw. Wenn Sie bereits über ein Build-Skript verfügen, ist das Verschieben in Jenkins ein guter erster Schritt, bevor Sie es umgestalten, um die Jenkins-Funktionen zu nutzen.
Aehlke
3
Vernetzung dieser Antwort serverfault.com/a/143576/186454 set + e und set -e können an einer beliebigen Stelle in Ihrem Skript angegeben werden. Jeder Code dazwischen wird den Build nicht fehlschlagen, wenn der zurückgegebene Wert nicht 0 ist.
Alex Skrypnyk
2
sehr gut gesagt auf dem Shell-Skript gegen Jenkins Set
Pushya
Wir verwenden Jenkins, um einen authentifizierten Zugriff und eine Benutzeroberfläche für den Job bereitzustellen. Ein Cron würde es nicht schneiden. Jenkins führt nicht nur Skripte aus.
ffghfgh
90

Einfache und kurze Antwort auf Ihre Frage ist

Bitte fügen Sie die folgende Zeile in Ihren Build-Schritt "Shell ausführen" ein.

#!/bin/sh

Lassen Sie mich nun den Grund erklären, warum wir diese Zeile für den Build-Job "Shell ausführen" benötigen.

Standardmäßig nimmt Jenkins take /bin/sh -xeund dies bedeutet , dass jeder Befehl -xgedruckt wird. Und die andere Option -e, die dazu führt, dass die Shell die Ausführung eines Skripts sofort beendet, wenn ein Befehl mit einem Exit-Code ungleich Null (wenn ein Befehl fehlschlägt) beendet wird.

Wenn Sie also das hinzufügen #!/bin/sh, können Sie ohne Option ausführen.

Abhijeet Kamble
quelle
4
Upvoted. Wusste nichts über die Standardeinstellung -xe. Als mein grep-Komman keine Zeichenfolge fand, schlug mein gesamtes Skript fehl, weil grep einen Rückgabewert ungleich 0
zurückgab
Hat super funktioniert! Die Verwendung bei meinen nicht entscheidenden Schritten, einem Bereinigungsschritt, der nur so etwas wie find . -name 'bower_components' -exec rm {} \;und in einigen Fällen fehlschlägt. Vielen Dank!
yorch
Dies löschte alles - 'Und die andere Option -e, die bewirkt, dass die Shell die Ausführung eines Skripts sofort beendet, wenn ein Befehl mit einem Exit-Code ungleich Null (wenn ein Befehl fehlschlägt) beendet wird.'
Paramvir Singh Karwal
3

Meiner Meinung -enach ist es eine wirklich schlechte Idee , die Option für Ihre Shell auszuschalten . Möglicherweise schlägt einer der Befehle in Ihrem Skript aufgrund vorübergehender Bedingungen wie Speicherplatzmangel oder Netzwerkfehlern fehl. Ohne-e Jenkins wird es nicht auffallen und wird glücklich weitermachen. Wenn Sie Jenkins für die Bereitstellung eingerichtet haben, kann dies dazu führen, dass fehlerhafter Code gepusht wird und Ihre Site heruntergefahren wird.

Wenn Ihr Skript eine Zeile enthält, in der ein Fehler erwartet wird, z. B. ein grep oder ein find, fügen Sie einfach hinzu || true am Ende dieser Zeile hinzu. Dies stellt sicher, dass die Leitung immer erfolgreich ist.

Wenn Sie diesen Exit-Code verwenden müssen, können Sie den Befehl entweder in Ihre if-Anweisung einfügen:

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

Oder Sie können den Rückkehrcode in Ihrer ||Klausel erfassen :

grep foo bar || ret=$?
Bryan Larsen
quelle
1
Danke Bryan. Du hast meinen Tag gerettet . Ich denke auch, dass es eine gute Idee ist, sowohl -x als auch -e einzuschalten. Damit Sie in Ihrem Jenkins-Protokoll sehen.
Bikal Basnet
2

Schlicht und einfach:

Wenn Jenkins sieht, dass der Build-Schritt (der auch ein Skript ist) mit einem Code ungleich Null beendet wird, wird der Build mit einer roten Kugel markiert (= fehlgeschlagen).

Warum genau das passiert, hängt von Ihrem Build-Skript ab.

Ich habe etwas Ähnliches aus einer anderen Perspektive geschrieben, aber vielleicht hilft es trotzdem, es zu lesen: Warum glaubt Jenkins, dass mein Build erfolgreich war?

sti
quelle
0

Wenn Sie also das hinzufügen #!/bin/sh, können Sie ohne Option ausführen.

Es half mir auch bei der Behebung eines Problems, bei dem ich ein Bash-Skript von Jenkins Master auf meinem Linux-Slave ausführte. Durch einfaches Hinzufügen #!/bin/bashmeines obigen Skripts im Block "Execute Shell" wurde mein Problem behoben, da ansonsten die von Windows Git bereitgestellte Version der Bash Shell ausgeführt wurde, die einen Fehler verursachte.

Shailender Singh
quelle
0

In Jenkins ver. 1.635 ist es unmöglich, eine native Umgebungsvariable wie diese anzuzeigen:

$BUILD_NUMBER or ${BUILD_NUMBER}

In diesem Fall müssen Sie es in einer anderen Variablen festlegen.

set BUILDNO = $BUILD_NUMBER
$BUILDNO
user10413452
quelle