Jak / kiedy funkcja Execute Shell oznacza kompilację jako awarię w Jenkins?

112

Horrory, które znalazłem, szukając odpowiedzi na to ...

OK, mam skrypt .sh, który robi prawie wszystko, co powinien zrobić Jenkins:

  • sprawdza źródła z SVN
  • zbudować projekt
  • wdraża projekt
  • czyści po sobie

Tak więc w Jenkinsie muszę tylko „zbudować” projekt, uruchamiając skrypt w poleceniu Execute Shell. Skrypt jest uruchamiany (źródła są pobierane, projekt jest budowany / wdrażany), ale następnie oznacza kompilację jako niepowodzenie: Krok kompilacji „Wykonaj powłokę” oznaczono kompilację jako niepowodzenie Nawet jeśli skrypt został pomyślnie uruchomiony! Próbowałem zamknąć skrypt za pomocą:

  • wyjście 0 (nadal oznacza to jako błąd)
  • wyjście 1 (zgodnie z oczekiwaniami oznacza to niepowodzenie)
  • brak polecenia wyjścia (oznacza to niepowodzenie)

Kiedy, jak i dlaczego funkcja Execute Shell oznacza moją kompilację jako awarię?

próbnik
źródło

Odpowiedzi:

131

Po pierwsze, najedź myszą na szary obszar poniżej. Nie stanowi części odpowiedzi, ale absolutnie należy powiedzieć:

Jeśli masz skrypt powłoki, który sam wykonuje „pobieranie, budowanie, wdrażanie”, to dlaczego używasz Jenkinsa? Rezygnujesz ze wszystkich funkcji Jenkinsa, które sprawiają, że jest tym, czym jest. Równie dobrze możesz mieć crona lub SVN po zatwierdzeniu, które wywołują skrypt bezpośrednio. Kluczowe znaczenie ma samodzielne sprawdzenie przez Jenkinsa SVN. Pozwala uruchamiać kompilacje tylko wtedy, gdy są zmiany (lub na czas lub ręcznie, jeśli wolisz). Śledzi zmiany między kompilacjami. Pokazuje te zmiany, dzięki czemu możesz zobaczyć, która kompilacja była dla którego zestawu zmian. Wysyła e-maile do osób odpowiedzialnych, gdy ich zmiany spowodowały pomyślną lub nieudaną kompilację (ponownie, zgodnie z preferencjami). Wyśle e-maile do osób odpowiedzialnych za poprawianie błędów kompilacji. I coraz więcej. Archiwizacja przez Jenkinsa artefaktów sprawia, że ​​są one również dostępne dla każdej kompilacji bezpośrednio z Jenkinsa. Chociaż nie jest tak istotny jak płatność SVN, jest to ponownie integralna część tego, co sprawia, że ​​jest to Jenkins. To samo z wdrażaniem. Jeśli nie masz jednego środowiska, wdrażanie zwykle odbywa się w wielu środowiskach. Jenkins może śledzić, w jakim środowisku jest wdrażana określona kompilacja (z określonym zestawem zmian SVN), korzystając z promocji. Zrezygnujesz z tego wszystkiego. Wygląda na to, że powiedziano ci „musisz użyć Jenkinsa”, ale tak naprawdę nie chcesz, a robisz to tylko po to, aby odciągnąć szefów od pleców, tylko po to, by zaznaczyć „tak, użyłem Jenkinsa”

Krótka odpowiedź brzmi: kod zakończenia ostatniego polecenia kroku kompilacji wykonania powłoki Jenkin jest tym, co określa powodzenie / niepowodzenie kroku kompilacji . 0- sukces, anything else- porażka. Należy zauważyć, że jest to określenie sukcesu / niepowodzenia etapu kompilacji , a nie całego przebiegu zadania . Na powodzenie / niepowodzenie całego przebiegu zadania może dodatkowo wpływać wiele kroków kompilacji oraz czynności i wtyczki po kompilacji.

Wspomniałeś Build step 'Execute shell' marked build as failure, więc skupimy się tylko na jednym kroku budowy. Jeśli krok budowania powłoki Wykonaj zawiera tylko jedną linię, która wywołuje skrypt powłoki, kod zakończenia skryptu powłoki określi powodzenie / niepowodzenie kroku kompilacji. Jeśli po wykonaniu skryptu powłoki masz więcej wierszy, dokładnie je przejrzyj, ponieważ to one mogą powodować awarię.

Na koniec przeczytaj tutaj Skrypt kompilacji Jenkinsa kończy działanie po wykonaniu testu Google . Nie jest to bezpośrednio związane z twoim pytaniem, ale zwróć uwagę na tę część dotyczącą uruchamiania przez Jenkinsa kroku kompilacji Execute Shell , jako skryptu powłoki z/bin/sh -xe

Te -eśrodki, że skrypt będzie opuszczające z niepowodzenia, nawet jeśli tylko 1 komenda nie powiedzie się, nawet jeśli nie sprawdzanie błędów dla tego polecenia (bo wyjść skryptów zanim dojdzie do sprawdzania błędów). Jest to sprzeczne z normalnym wykonywaniem skryptów powłoki, które zwykle wyświetlają komunikat o błędzie dla nieudanego polecenia (lub przekierowują go do wartości null i obsługują w inny sposób) i kontynuują.

Aby to obejść, dodaj set +ena początku skryptu powłoki.

Ponieważ mówisz, że twój skrypt robi wszystko, co powinien, jest szansa, że ​​niepowodzenie polecenia znajduje się gdzieś na końcu skryptu. Może ostatnie echo? Albo gdzieś kopia artefaktów? Nie widząc pełnego wyniku konsoli, po prostu zgadujemy.

Opublikuj wyjście konsoli uruchomienia zadania, a najlepiej również sam skrypt powłoki, a wtedy możemy powiedzieć dokładnie, która linia nie działa.

słowiański
źródło
6
Powód, dla którego nadal używam Jenkinsa, jest dla mnie niejasny ... Wygląda na to, że ktoś na górze nie do końca zrozumiał, że mamy już ten skrypt i nalegał, abyśmy używali Jenkinsa. Czuję się jak w striptizie Dilberta. Dziękuję za -e napiwek. To rozwiązało problem
tester
45
Nadal istnieją dobre powody, aby używać Jenkinsa: ścieżka audytu, widoczność stanu kompilacji itp. Jeśli masz już skrypt kompilacji, przeniesienie go do Jenkinsa jest dobrym pierwszym krokiem przed jego refaktoryzacją w celu wykorzystania funkcji Jenkinsa.
aehlke
3
Łączenie tej odpowiedzi serverfault.com/a/143576/186454 set + e i set -e można określić w dowolnym miejscu skryptu. Każdy kod pomiędzy nimi nie zakończy kompilacji, jeśli zwrócona wartość nie będzie równa 0.
Alex Skrypnyk
2
bardzo dobrze powiedziane na temat skryptu powłoki vs set
jenkins
używamy jenkins, aby zapewnić uwierzytelniony dostęp i interfejs użytkownika do pracy. Cron by tego nie wyciął. Jenkins nie tylko prowadzi cripts.
ffghfgh
90

Prosta i krótka odpowiedź na Twoje pytanie brzmi

Dodaj następujący wiersz do kroku kompilacji „Wykonaj powłokę”.

#!/bin/sh

Pozwólcie, że wyjaśnię wam teraz powód, dla którego potrzebujemy tego wiersza do zadania budowania „Execute Shell”.

Domyślnie Jenkins bierze, /bin/sh -xea to oznacza, -xże wypisuje każde polecenie i drugą opcję -e, która powoduje, że powłoka natychmiast przestaje uruchamiać skrypt, gdy dowolne polecenie kończy się z niezerowym kodem zakończenia (gdy jakiekolwiek polecenie nie powiedzie się).

Więc dodając #!/bin/shpozwoli ci wykonać bez opcji.

Abhijeet Kamble
źródło
4
Głosowano za. Nie wiedziałem o domyślnej opcji -xe. Kiedy mój grep comman nie znalazł ciągu, cały skrypt zawiódł, ponieważ grep zwrócił wartość
zwrotną inną
Działało świetnie! Używając go na moich nie-kluczowych krokach, kroku czyszczenia, który po prostu robi coś podobnego, find . -name 'bower_components' -exec rm {} \;aw niektórych przypadkach kończy się niepowodzeniem. Dzięki!
yorch
to wyczyściło wszystko - „I druga opcja -e, która powoduje, że powłoka natychmiast przerywa wykonywanie skryptu, gdy jakakolwiek komenda kończy działanie z niezerowym kodem zakończenia (gdy jakiekolwiek polecenie nie powiedzie się)”.
Paramvir Singh Karwal
3

Moim zdaniem wyłączenie -eopcji w Twojej powłoce to naprawdę zły pomysł. Ostatecznie jedno z poleceń w skrypcie zakończy się niepowodzeniem z powodu przejściowych warunków, takich jak brak miejsca na dysku lub błędy sieciowe. Bez -eJenkinsa tego nie zauważy i będzie kontynuował szczęśliwie. Jeśli masz skonfigurowany Jenkins do wdrożenia, może to spowodować wypchnięcie złego kodu i wyłączenie witryny.

Jeśli masz w swoim skrypcie linię, w której oczekiwana jest awaria, na przykład grep lub find, po prostu dodaj || truena końcu tej linii. To gwarantuje, że ta linia zawsze zwróci sukces.

Jeśli chcesz użyć tego kodu zakończenia, możesz przenieść polecenie do instrukcji if:

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

Lub możesz przechwycić kod powrotu w swojej ||klauzuli:

grep foo bar || ret=$?
Bryan Larsen
źródło
1
Dzięki Bryan. Uratowałeś mi dzień. Myślę też, że dobrym pomysłem jest włączenie obu opcji -x i -e. Abyś zobaczył w swoim dzienniku Jenkinsa.
Bikal Basnet
2

Jasne i proste:

Jeśli Jenkins zobaczy, że krok kompilacji (który również jest skryptem) kończy się z kodem niezerowym, kompilacja jest oznaczana czerwoną kulką (= niepowodzenie).

Dlaczego dokładnie tak się dzieje, zależy od twojego skryptu kompilacji.

Napisałem coś podobnego z innego punktu widzenia, ale może i tak pomoże to przeczytać: Dlaczego Jenkins uważa, że ​​moja konstrukcja się powiodła?

sti
źródło
0

Więc dodając #!/bin/shpozwoli ci wykonać bez opcji.

Pomogło mi to również w naprawieniu problemu, w którym wykonywałem skrypt bash z mistrza Jenkinsa na moim niewolniku Linuksa. Po prostu dodanie #!/bin/bashpowyżej mojego aktualnego skryptu w bloku „Execute Shell” naprawiło mój problem, ponieważ w przeciwnym razie wykonywał on wersję powłoki bash dostarczoną przez git systemu Windows, która dawała błąd.

Shailender Singh
źródło
0

W Jenkins ver. 1.635, niemożliwe jest pokazanie natywnej zmiennej środowiskowej w ten sposób:

$BUILD_NUMBER or ${BUILD_NUMBER}

W takim przypadku musisz ustawić go w innej zmiennej.

set BUILDNO = $BUILD_NUMBER
$BUILDNO
user10413452
źródło