Niezerowy status wyjścia dla czystego wyjścia

15

Czy dopuszczalne jest zwrócenie niezerowego kodu wyjścia, jeśli program działał poprawnie? Powiedzmy na przykład, że mam prosty program, który (tylko) wykonuje następujące czynności:

Program przyjmuje N argumentów. Zwraca kod wyjścia min (N, 255). Zauważ, że dowolne N jest ważne dla programu.

Bardziej realistyczny program może zwracać różne kody dla pomyślnie uruchomionych programów, które oznaczają różne rzeczy. Czy te programy powinny zamiast tego zapisywać te informacje w strumieniu, na przykład na standardowym wyjściu?

Thomas Eding
źródło

Odpowiedzi:

24

To zależy od środowiska, ale powiedziałbym, że to zły styl.

Systemy uniksowe mają silną konwencję, że status wyjścia 0 oznacza sukces, a każdy niezerowy status wyjścia oznacza niepowodzenie. Niektóre, ale nie wszystkie, programy rozróżniają różne rodzaje awarii za pomocą różnych niezerowych kodów wyjścia; na przykład grepzwykle zwraca 0, jeśli wzorzec został znaleziony, 1, jeśli nie został, i 2 (lub więcej), jeśli wystąpił błąd, taki jak brakujący plik.

Ta konwencja jest dość mocno połączona z powłokami uniksowymi. Na przykład, w sh, bashi innych powłokach podobnych do Bourne'a, ifinstrukcja traktuje status wyjścia 0 jako sukces / prawda, a niezerowy status wyjścia jako niepowodzenie / fałsz:

if your-command
then
    echo ok
else
    echo FAILURE
fi

Uważam, że konwencje w MS Windows są podobne.

Teraz z pewnością nic nie stoi na przeszkodzie, aby napisać własny program, który używa niekonwencjonalnych kodów wyjścia, szczególnie jeśli nic innego nie będzie z nim współdziałać, ale pamiętaj, że naruszasz ustaloną konwencję, a może on wrócić i ugryźć cię później .

Zwykłym sposobem na zwrócenie tego rodzaju informacji przez program jest wydrukowanie ich na stdout:

status = $(your-command)
echo Result is $status
Keith Thompson
źródło
7
+1 za wyjaśnienie konwencji, takie podejście złamałoby większość moich skryptów powłoki, gdybym set -egdzieś tam umieścił .
Benjamin Bannier
Podobnie grep, diffzwraca 1, gdy zostaną znalezione różnice; i> 1, jeśli wystąpił błąd.
7heo.tk
6

Zależy od tego, czego oczekuje twoje środowisko.

Moje ulubione dziwactwo, z Wikipedii :

W OpenVMS sukces jest wskazywany przez wartości nieparzyste, a niepowodzenie przez wartości parzyste. Wartością jest 32-bitowa liczba całkowita z podpolami: bitami kontrolnymi, numerem urządzenia, numerem komunikatu i istotnością. Wartości ważności dzielone są między sukces (sukces, informacja) i niepowodzenie (ostrzeżenie, błąd, błąd krytyczny).

Rachunek
źródło
4

Myślę, że istnieje precedens, jeśli kod zakończenia zwraca znaczącą, istotną informację do dzwoniącego, a definicja sukcesu nie jest naprawdę binarna. Moim precedensem jest robocopy, które zwracają mnóstwo różnych rzeczy w zależności od tego, co się wydarzyło .

Dodam, że zawsze kończy się to z powodu tego debugowania - większość narzędzi zakłada, że ​​kod wyjścia 0 == sukces, więc denerwuj się, gdy robocopy zwraca 1, ponieważ kopiuje rzeczy nie zero, ponieważ nie kopiuje rzeczy, ale nie robi t pojawia się błąd.

Wyatt Barnett
źródło
2

nie zwracanie wartości 0 dla pomyślnego uruchomienia jest złym pomysłem, ponieważ może powodować zamieszanie u osób uruchamiających program. Co się stanie, jeśli niektórzy uruchomili Twój program ponad 100 razy z różnymi danymi wejściowymi i chcieli wiedzieć, ile z nich zakończyło się niepowodzeniem lub sukcesem, mając jedną wartość sukcesu znacznie łatwiej dostrzec różnice niż mieć wiele różnych wartości.

Jeśli masz program, który ma wiele udanych ścieżek zwrotnych, które wszystkie mogą oznaczać różne rzeczy, powiedziałbym, że jest to znak, że twój program jest źle zaprojektowany.

Ryathal
źródło
2

Znam przypadek, który moim zdaniem jest do zaakceptowania. Znam strukturę testowania, która kończy się wraz z całkowitą liczbą niepowodzeń testowych. Na przykład, jeśli testujący zakończy się bez żadnych nieudanych testów, zakończy działanie z zerem. Jeśli jeden test się nie powiedzie, mimo że sam tester uruchomił się poprawnie, kończy się z jednym 1. Jeśli dwa testy zakończą się niepowodzeniem, zwraca 2, itd. To wzrasta do 250, co oznacza „250 lub więcej błędów testu”.

Używa kodów wyjścia> 250 w celu oznaczenia nieprawidłowych wyjść.

Chociaż narusza to konwencję, działa dobrze w praktyce.

Bryan Oakley
źródło
3
Nie sądzę, że narusza to konwencję - testowanie kończy się powodzeniem, jeśli nie ma błędów; każdy niezerowy kod wyniku wskazuje, że testy zakończyły się niepowodzeniem.
Bevan
1
To „wychodzenie ze statusem błędu w celu wskazania więcej niż 0 błędów” i chociaż może to naruszać dokładną wspólną semantykę statusu wyjścia, z pewnością nie narusza większej „0 jest OK, wszystko większe niż 0 jest konwencją błędu” .
Vatine
2

To naprawdę zależy od tego, co próbujesz przekazać kodem. Na przykład DB2 zwraca 100, jeśli nie znaleziono danych, różne inne wartości dodatnie dla ostrzeżeń i wartości ujemne dla błędów. Oracle robi coś podobnego.

Tak więc, jeśli istnieją różne stany sukcesu, warto zastosować różne wartości zwracane.

Matthew Flynn
źródło
2

Dobry przykład: man sa-update (spamassassin)

KODY WYJŚCIA

  • Kod wyjścia 0 oznacza, że ​​aktualizacja była dostępna i została pobrana i zainstalowana pomyślnie, jeśli nie podano opcji --checkonly.
  • Kod wyjścia 1 oznacza, że ​​nie były dostępne nowe aktualizacje.
  • Kod wyjścia 2 oznacza ...

W takim przypadku wyjście 1 jest po prostu kodem informacyjnym. Gdybym jednak napisał kod, nie wybrałbym 1, ponieważ zwykle jest to awaria sieci.

Wynicować
źródło