it-swarm.com.de

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

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

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

  • prüft Quellen aus SVN
  • baue das Projekt
  • setzt das Projekt ein
  • reinigt nach sich selbst

In Jenkins muss ich also nur das Projekt "erstellen", indem ich das Skript in einem Execute Shell-Befehl ausführte. Das Skript wird ausgeführt (die Quellen werden heruntergeladen, das Projekt ist build/deploy), markiert jedoch den Build als fehlerhaft: Build-Schritt 'Execute Shell' markiert Build als fehlgeschlagen Auch wenn das Script erfolgreich ausgeführt wurde ! Ich habe versucht, das Skript zu schließen mit:

  • exit 0 (kennzeichnet es immer noch als fehlerhaft)
  • exit 1 (kennzeichnet es wie erwartet als fehlerhaft)
  • kein Exit-Befehl (kennzeichnet es als Fehlschlag)

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

101
tester

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

Wenn Sie ein Shell-Skript haben, das von alleine "checkout, build, deploy" ausführt, warum verwenden Sie dann Jenkins? Sie verzichten auf alle Funktionen von Jenkins, die es zu dem machen, was es ist. Sie könnten das Skript auch direkt mit einem cron- oder SVN-Hook nach dem Commit aufrufen. Jenkins führt die SVN-Prüfung selbst durch. Die Builds können nur dann ausgelöst werden, wenn Änderungen vorgenommen wurden (oder der Timer oder manuell, wenn Sie möchten). Es verfolgt Änderungen zwischen Builds. Es zeigt diese Änderungen, sodass Sie sehen können, welcher Build für welche Änderungen verwendet wurde. Er sendet den E-Mails eine E-Mail, wenn ihre Änderungen zu einem erfolgreichen oder fehlgeschlagenen Build geführt haben (wiederum wie gewünscht konfiguriert). Er wird den Commitenten eine E-Mail senden, wenn ihre Korrekturen den fehlerhaften Build behoben haben. Und immer mehr. Durch die Archivierung der Artefakte von Jenkins sind sie auch pro Build direkt ab Jenkins verfügbar. Obwohl dies nicht so wichtig ist wie die SVN-Kasse, ist dies wieder ein wesentlicher Bestandteil dessen, was es zu Jenkins macht. Gleiches gilt für die Bereitstellung. Wenn Sie nicht über eine einzige Umgebung verfügen, erfolgt die Bereitstellung normalerweise in mehreren Umgebungen. Jenkins kann mithilfe von Promotions nachverfolgen, in welcher Umgebung ein bestimmter Build (mit bestimmten SVN-Änderungen) bereitgestellt wird. Sie verzichten auf all das. Es klingt, als würde man Ihnen sagen, "Sie müssen Jenkins benutzen", aber Sie wollen es nicht wirklich, und Sie tun es nur, um Ihre Chefs vom Rücken zu bekommen, nur um ein Häkchen zu setzen "Ja, ich habe Jenkins benutzt"

Die kurze Antwort lautet: Der Exit-Code des Befehls last des Buildschritts Execute Shell von Jenkin bestimmt den Erfolg/Misserfolg des Build Step. 0 - success, anything else - failure . Beachten Sie, dass dies den Erfolg/Misserfolg des build-Schritts bestimmt, nicht den gesamten Joblauf. Der Erfolg/Misserfolg des gesamten Auftragslaufs kann außerdem durch mehrere Erstellungsschritte sowie Nachbearbeitungsaktionen und Plugins beeinflusst werden.

Sie haben Build step 'Execute Shell' marked build as failure erwähnt, also konzentrieren wir uns nur auf einen einzelnen Build-Schritt. Wenn Ihr Erstellungsschritt Execute Shell nur über eine einzige Zeile verfügt, die Ihr Shell-Skript aufruft, bestimmt der Beendigungscode Ihres Shell-Skripts, ob der Erstellungsschritt erfolgreich abgeschlossen wurde. Wenn Sie mehr Zeilen haben, after nach der Ausführung Ihres Shell-Skripts, überprüfen Sie diese sorgfältig, da sie möglicherweise fehlerhaft sind.

Zum Schluss lesen Sie hier Jenkins Build Script wird nach der Ausführung von Google Test beendet. Es ist nicht direkt mit Ihrer Frage verbunden. Beachten Sie jedoch, dass Jenkins den Buildschritt Execute Shell als Shell-Skript mit /bin/sh -xe startet.

Der -e bedeutet, dass das Shell-Skript exit mit einem Fehler ausfällt, selbst wenn nur ein Befehl fehlschlägt, even, wenn Sie eine Fehlerprüfung für diesen Befehl durchführen (da das Skript beendet wird, bevor es zur Fehlerprüfung kommt). Dies steht im Gegensatz zur normalen Ausführung von Shell-Skripts, die normalerweise die Fehlernachricht für den fehlgeschlagenen Befehl ausgeben (oder auf Null umleiten und auf andere Weise behandeln) und fortfahren.

Um dies zu umgehen, fügen Sie set +e oben in Ihr Shell-Skript ein.

Da Sie sagen, dass Ihr Skript alles tut, was es tun soll, stehen die Chancen, dass der fehlgeschlagene Befehl irgendwo am Ende des Skripts liegt. Vielleicht ein endgültiges Echo? Oder irgendwo eine Kopie von Artefakten? Ohne die volle 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 fehlerhaft ist.

119
Slav

Eine einfache und kurze Antwort auf Ihre Frage ist

Fügen Sie dem Build-Schritt "Shell ausführen" die folgende Zeile hinzu.

#!/bin/sh

Lassen Sie mich nun den Grund erläutern, warum wir diese Zeile für den Buildjob "Execute Shell" benötigen.

Standardmäßig verwendet Jenkins /bin/sh -xe. Dies bedeutet, dass -x jeden Befehl druckt. Und die andere Option -e bewirkt, dass Shell die Ausführung eines Skripts sofort beendet, wenn ein Befehl mit einem Exit-Code endet, der nicht null ist (wenn ein Befehl fehlschlägt). 

Durch das Hinzufügen von #!/bin/sh können Sie also keine Option ausführen.

80
Abhijeet Kamble

Schlicht und einfach:

Wenn Jenkins sieht, dass der Build-Schritt (der ebenfalls ein Skript ist) mit Nicht-Null-Code beendet wird, wird der Build mit einer roten Kugel markiert (= nicht bestanden).

Warum genau dies geschieht, hängt von Ihrem Build-Skript ab.

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

2
sti

Meines Erachtens ist das Deaktivieren der -e-Option für Ihre Shell eine wirklich schlechte Idee. Möglicherweise schlägt einer der Befehle in Ihrem Skript aufgrund vorübergehender Bedingungen wie zu wenig Festplattenspeicher oder Netzwerkfehlern fehl. Ohne -e wird Jenkins nichts bemerken und geht glücklich weiter. Wenn Sie Jenkins für die Bereitstellung eingerichtet haben, kann dies dazu führen, dass fehlerhafter Code verschoben und Ihre Website heruntergefahren wird.

Wenn sich in Ihrem Skript eine Zeile befindet, in der ein Fehler erwartet wird, z. B. ein grep oder ein find, fügen Sie am Ende dieser Zeile einfach || true hinzu. Dies stellt sicher, dass diese Linie immer wieder Erfolg bringt.

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=$?
2
Bryan Larsen

Durch das Hinzufügen von #!/bin/sh können Sie also keine Option ausführen.

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

0

In Jenkins ver. 1.635 ist es nicht möglich, eine native Umgebungsvariable wie folgt anzuzeigen:

$ BUILD_NUMBER oder $ {BUILD_NUMBER}

In diesem Fall müssen Sie es in eine andere Variable setzen.

set BUILDNO = $ BUILD_NUMBER $ BUILDNO

0
user10413452