Uważa się, że proces zakończył się poprawnie w systemie Linux, jeśli jego kodem zakończenia było 0.
Widziałem, że błędy segmentacji często skutkują statusem wyjścia 11, choć nie wiem, czy to po prostu konwencja, w której pracuję (aplikacje, które zawiodły, wszystkie były wewnętrzne), czy standard.
Czy istnieją standardowe kody wyjścia dla procesów w systemie Linux?
linux
error-handling
exit-code
Nathan Fellman
źródło
źródło
Odpowiedzi:
8 bitów kodu powrotu i 8 bitów liczby sygnału zabijania są mieszane w jedną wartość po powrocie z
wait(2)
& co. .Jak określasz status wyjścia? Tradycyjnie powłoka przechowuje tylko 8-bitowy kod powrotu, ale ustawia wysoki bit, jeśli proces został nieprawidłowo zakończony.
Jeśli widzisz coś innego niż to, program prawdopodobnie ma
SIGSEGV
moduł obsługi sygnału, który następnie wywołujeexit
normalnie, więc tak naprawdę nie zostaje zabity przez sygnał. (Programy mogą obsługiwać wszelkie sygnały opróczSIGKILL
iSIGSTOP
.)źródło
Część 1: Podręcznik zaawansowanego skryptu Bash
Jak zawsze, Advanced Bash Scripting Guide ma świetne informacje : (To było połączone w innej odpowiedzi, ale z niekanonicznym adresem URL).
Część 2: sysexits.h
Referencje ABSG
sysexits.h
.W systemie Linux:
źródło
man sysexits
sysexits.h
? Strona człowiek każdy trzyma odsyłania tylko proza. Na przykład odwołuje się,EX_OK
ale tak naprawdę nie definiuje go w sposób normatywny, jak inne kody. Czy brakuje czegoś więcej?„1” >>> Catchall dla błędów ogólnych
„2” >>> Niewłaściwe użycie wbudowanych powłok (zgodnie z dokumentacją Bash)
„126” >>> Wywołane polecenie nie może zostać wykonane
„127” >>> „Nie znaleziono polecenia”
„128” >>> Niepoprawny argument do wyjścia
„128 + n” >>> Sygnał błędu krytycznego „n”
„130” >>> Skrypt zakończony przez Control-C
„255” >>> Wyjdź ze statusu poza zakresem
To jest bash. Jednak w przypadku innych aplikacji istnieją różne kody wyjścia.
źródło
Żadna ze starszych odpowiedzi nie opisuje poprawnie wyjścia 2. W przeciwieństwie do tego, co twierdzą, status 2 jest tym, co narzędzia wiersza poleceń faktycznie zwracają, gdy są wywoływane nieprawidłowo. (Tak, odpowiedź może mieć dziewięć lat, mieć setki pozytywnych opinii i nadal być w błędzie).
Oto prawdziwa, długotrwała konwencja statusu wyjścia dla normalnego zakończenia, tzn. Nie przez sygnał:
Na przykład
diff
zwraca 0, jeśli porównywane pliki są identyczne, a 1, jeśli się różnią. Zgodnie z wieloletnią konwencją programy uniksowe zwracają status wyjścia 2, gdy są niepoprawnie wywoływane (nieznane opcje, zła liczba argumentów itp.) Na przykładdiff -N
,grep -Y
lubdiff a b c
wszystkie spowodują$?
ustawienie na 2. Jest to i było praktyką, ponieważ wczesne dni Uniksa w latach 70.Odpowiedź Zaakceptowany wyjaśnia, co się dzieje, gdy polecenie jest zakończony przez sygnał. W skrócie, zakończenie z powodu nieprzechwyconego sygnału powoduje status wyjścia
128+[<signal number>
. Np. Zakończenie przezSIGINT
( sygnał 2 ) powoduje status wyjścia 130.Notatki
Kilka odpowiedzi definiuje status wyjścia 2 jako „Niewłaściwe użycie wbudowanych bashów”. Ma to zastosowanie tylko wtedy, gdy bash (lub skrypt bash) kończy się ze statusem 2. Rozważ to szczególny przypadek nieprawidłowego użycia błędu.
W
sysexits.h
, wspomnianym w najpopularniejszej odpowiedzi , status wyjściaEX_USAGE
(„błąd użycia wiersza poleceń”) jest zdefiniowany jako 64. Ale to nie odzwierciedla rzeczywistości: nie znam żadnego wspólnego narzędzia uniksowego, które zwraca 64 przy nieprawidłowym wywołaniu (mile widziane przykłady ). Uważne czytanie kodu źródłowego ujawnia, żesysexits.h
jest ono raczej aspiracyjne niż odzwierciedleniem prawdziwego użycia:Innymi słowy, definicje te nie odzwierciedlają powszechnej wówczas praktyki (1993), ale celowo były z nią niezgodne. Więcej szkoda.
źródło
more
zresetuje tryby terminalu i wyjdzie ze statusem 0 (możesz spróbować).Nie ma standardowych kodów wyjścia, poza 0, co oznacza sukces. Niezerowa również niekoniecznie oznacza awarię.
stdlib.h definiuje
EXIT_FAILURE
jako 1 iEXIT_SUCCESS
jako 0, ale o to chodzi.11 na segfault jest interesujące, ponieważ 11 to numer sygnału, którego jądro używa do zabicia procesu w przypadku wystąpienia segfault. Prawdopodobnie istnieje jakiś mechanizm, albo w jądrze, albo w powłoce, który tłumaczy to na kod wyjścia.
źródło
sysexits.h ma listę standardowych kodów wyjścia. Wygląda na to, że datuje się na co najmniej 1993 r., A niektóre duże projekty, takie jak Postfix, używają go, więc wyobrażam sobie, że tak należy.
Ze strony podręcznika OpenBSD:
źródło
W pierwszym przybliżeniu 0 oznacza powodzenie, niezerowe oznacza awarię, przy czym 1 oznacza awarię ogólną, a wszystko większe niż jedno oznacza awarię konkretną. Oprócz trywialnych wyjątków fałszowania i testowania, które są zaprojektowane tak, aby dać 1 dla powodzenia, znalazłem kilka innych wyjątków.
Bardziej realistycznie, 0 oznacza sukces, a może porażkę, 1 oznacza ogólną porażkę, a może sukces, 2 oznacza ogólną porażkę, jeśli 1 i 0 są użyte zarówno do sukcesu, ale może również sukcesu.
Polecenie diff daje 0, jeśli porównywane pliki są identyczne, 1, jeśli się różnią, i 2, jeśli pliki binarne są różne. 2 oznacza także awarię. Komenda less daje 1 za niepowodzenie, chyba że nie podasz argumentu, w którym to przypadku kończy 0, pomimo niepowodzenia.
Komenda more i komenda spell dają 1 za niepowodzenie, chyba że niepowodzenie jest wynikiem odmowy dostępu, nieistniejącego pliku lub próby odczytania katalogu. W każdym z tych przypadków wychodzą one z wartości 0 pomimo niepowodzenia.
Następnie polecenie expr daje 1 dla powodzenia, chyba że wynikiem jest pusty ciąg znaków lub zero, w którym to przypadku 0 oznacza powodzenie. 2 i 3 są porażką.
Są też przypadki, w których sukces lub porażka są niejednoznaczne. Gdy grep nie znajdzie wzorca, kończy 1, ale kończy 2 dla prawdziwej awarii (np. Odmowa zgody). Klist wychodzi również z 1, gdy nie może znaleźć biletu, chociaż tak naprawdę nie jest to więcej niż awaria niż wtedy, gdy grep nie znajduje wzorca lub gdy masz pusty katalog.
Tak więc, niestety, moce uniksowe, które wydają się nie wymuszać żadnego logicznego zestawu reguł, nawet w przypadku bardzo często używanych plików wykonywalnych.
źródło
Programy zwracają 16-bitowy kod wyjścia. Jeśli program został zabity sygnałem, wówczas bajt wysokiego rzędu zawiera używany sygnał, w przeciwnym razie bajt niskiego rzędu to status wyjścia zwracany przez programistę.
Jak ten kod wyjścia jest przypisany do zmiennej statusu $? zależy od powłoki. Bash zachowuje 7 niższych bitów statusu, a następnie używa 128 + (nr sygnału) do wskazania sygnału.
Jedyną „standardową” konwencją dla programów jest 0 dla sukcesu, a niezerowa dla błędu. Inną stosowaną konwencją jest zwracanie errno po błędzie.
źródło
Standardowe kody wyjścia Unix są zdefiniowane przez sysexits.h, jak wspomniano w innym plakacie. Te same kody wyjścia są używane przez biblioteki przenośne, takie jak Poco - oto ich lista:
http://pocoproject.org/docs/Poco.Util.Application.html#16218
Sygnał 11 jest sygnałem SIGSEGV (naruszenie segmentu), który różni się od kodu powrotu. Jądro generuje ten sygnał w odpowiedzi na zły dostęp do strony, co powoduje zakończenie programu. Listę sygnałów można znaleźć na stronie man sygnału (uruchom „man signal”).
źródło
Kiedy Linux zwraca 0, oznacza to sukces. Wszystko inne oznacza awarię, każdy program ma własne kody zakończenia, więc lista wszystkich z nich byłaby dość długa ...!
W przypadku kodu błędu 11 jest to rzeczywiście numer błędu segmentacji, co w większości oznacza, że program uzyskał dostęp do pamięci, która nie została przypisana.
źródło