Jaka jest różnica między instrukcją return
i exit
w funkcjach Bash w odniesieniu do kodów wyjścia?
Jaka jest różnica między instrukcją return
i exit
w funkcjach Bash w odniesieniu do kodów wyjścia?
Odpowiedzi:
Od man bash
dnia return [n]
;
Powoduje, że funkcja przestaje działać i zwraca wartość określoną przez n do swojego obiektu wywołującego. Jeśli pominięto n, zwracany jest status ostatniego polecenia wykonanego w treści funkcji.
... w dniu exit [n]
:
Powoduje zamknięcie powłoki ze statusem n. Jeśli n zostanie pominięte, kodem zakończenia jest status ostatniego wykonanego polecenia. Pułapka na EXIT jest wykonywana przed zakończeniem powłoki.
EDYTOWAĆ:
Zgodnie z edycją pytania dotyczącego kodów wyjścia, return
nie ma to nic wspólnego z kodami wyjścia. Kody wyjścia są przeznaczone dla aplikacji / skryptów , a nie funkcji. W związku z tym jedynym słowem kluczowym, które ustawia kod wyjścia skryptu (ten, który może zostać przechwycony przez program wywołujący za pomocą $?
zmiennej powłoki) jestexit
.
EDYCJA 2:
Moje ostatnie stwierdzenie, które odsyłam, exit
powoduje komentarze. Zostało stworzone w celu odróżnienia return
i exit
zrozumienia PO, a tak naprawdę w dowolnym punkcie skryptu programu / powłoki,exit
jest to jedyny sposób na zakończenie skryptu kodem wyjścia dla procesu wywołującego.
Każda komenda wykonana w powłoce wytwarza lokalną „Kod wyjścia”: ustawia $?
zmienną do tego kodu, i może być stosowany z if
, &&
i inni operatorzy warunkowo wykonywanie innych poleceń.
Te kody wyjścia (i wartość $?
zmiennej) są resetowane przy każdym wykonaniu polecenia.
Nawiasem mówiąc, kod wyjścia ostatniego polecenia wykonanego przez skrypt jest używany jako kod wyjścia samego skryptu, jak widać w procesie wywołującym.
Wreszcie, wywołane funkcje działają jak polecenia powłoki względem kodów wyjścia. Kod wyjścia funkcji ( w ramach funkcji) ustawia się za pomocą return
. Kiedy więc funkcja return 0
jest uruchomiona, wykonywanie funkcji kończy się, dając kod wyjścia 0.
func(){ return 50; };func;echo $?
echo 50. Zatem $?
zmienna powłoki nie wydaje się ograniczona exit
.
$?
Rozwija się do statusu wyjścia ostatnio wykonanego rurociągu pierwszego planu.” Wyjście może pochodzić z powłoki w formie wywołania exit
(lub uderzenia w koniec skryptu) lub w formie wywołania return
funkcji.
$?
Bieżący proces / skrypt jest ograniczony albo do exit
wyniku ostatniego polecenia wykonanego przez ten skrypt. Tak więc, jeśli ostatni wiersz skryptu to wywołanie tej funkcji, a ta funkcja zwraca 50, tak, to $?
, co produkujesz do procesu, który cię wezwał, to 50. Jednak to nie ma nic wspólnego z return
, ponieważ jest to ograniczony do bieżącego skryptu. Zdarza się, że jest zwracane tylko wtedy, gdy to wywołanie funkcji jest ostatnim zdaniem skryptu. exit
, jednak zawsze kończ skrypt i zwracaj tę wartość co $?
do procesu wywoływania .
return
nie ma nic wspólnego z kodami wyjścia”. Eksperymentowanie mówi mi, że nie ma funkcjonalnej różnicy między kodem powrotu funkcji a kodem wyjścia skryptu.
return
spowoduje, że bieżąca funkcja wyjdzie poza zakres, a exit
skrypt zakończy się w punkcie, w którym zostanie wywołana. Oto przykładowy program, który pomoże to wyjaśnić:
#!/bin/bash
retfunc()
{
echo "this is retfunc()"
return 1
}
exitfunc()
{
echo "this is exitfunc()"
exit 1
}
retfunc
echo "We are still here"
exitfunc
echo "We will never see this"
$ ./test.sh
this is retfunc()
We are still here
this is exitfunc()
$?
.
echo fnord | while read x; do exitfunc; done; echo "still here"
wydrukuje „wciąż tutaj”. Wydaje się, że while
w tym scenariuszu wychodzi tylko podpowłoka.
done || exit $?
jednak brzydkie i nie do końca równoważne.
return
spowoduje, że bieżąca funkcja lub skrypt źródłowy wykroczą poza zakres ''.
Nie sądzę, aby ktokolwiek tak naprawdę w pełni odpowiedział na pytanie, ponieważ nie opisuje, w jaki sposób są one używane. OK. Myślę, że wiemy, że exit zabija skrypt, gdziekolwiek jest on wywoływany, i można przypisać mu status, np. Exit lub exit 0 lub exit 7 i tak dalej. Można to wykorzystać do ustalenia, w jaki sposób skrypt został zmuszony do zatrzymania, jeśli został wywołany przez inny skrypt itp. Wystarczy przy wyjściu.
return, gdy zostanie wywołany, zwróci wartość określoną w celu wskazania zachowania funkcji, zwykle 1 lub 0. Na przykład:
#!/bin/bash
isdirectory() {
if [ -d "$1" ]
then
return 0
else
return 1
fi
echo "you will not see anything after the return like this text"
}
sprawdź tak:
if isdirectory $1; then echo "is directory"; else echo "not a directory"; fi
lub tak:
isdirectory || echo "not a directory"
W tym przykładzie test można wykorzystać do wskazania, czy katalog został znaleziony. zauważ, że cokolwiek po zwrocie nie zostanie wykonane w funkcji. 0 to prawda, ale fałsz to 1 w powłoce, różny od innych języków prog.
Aby uzyskać więcej informacji na temat funkcji: http://www.linuxjournal.com/content/return-values-bash-functions
UWAGA: Funkcja isdirectory służy wyłącznie do celów instruktażowych. Nie powinno tak być w przypadku wykonywania takiej opcji w prawdziwym skrypcie.
test -d $1
aby osiągnąć ten sam wynik. Nigdy nie rób if <check> return else return
. <check>
sam zrobi to samo we wszystkich językach, które znam przynajmniej.
isdirectory() { [ -d "$1" ]; }
zachowa się dokładnie tak samo, jak tutaj: Domyślna wartość zwracana przez funkcję powłoki, czy to po osiągnięciu końca kodu, czy też return
bez argumentów, jest wartością parametru ostatnie polecenie.
return
wypowiedzi. To prawda, że jego przykład jest uproszczony i nie może być wykorzystywany w produkcji. Ale to proste, więc dobrze spełnia swoje zadanie. Nie ma w tym nic złego.
Pamiętaj, że funkcje są wewnętrzne dla skryptu i zwykle zwracają skąd zostały wywołane za pomocą instrukcji return. Wywołanie zewnętrznego skryptu to zupełnie inna sprawa, a skrypty zwykle kończą się instrukcją exit.
Różnica „między instrukcją return i exit w funkcjach BASH w odniesieniu do kodów wyjścia” jest bardzo niewielka. Oba zwracają status, a nie same wartości . Status zero oznacza sukces, a każdy inny status (od 1 do 255) oznacza awarię. Instrukcja return powróci do skryptu, z którego została wywołana, a instrukcja exit zakończy cały skrypt od momentu napotkania.
return 0 # returns to where the function was called. $? contains 0 (success).
return 1 # returns to where the function was called. $? contains 1 (failure).
exit 0 # exits the script completely. $? contains 0 (success).
exit 1 # exits the script completely. $? contains 1 (failure).
Jeśli funkcja kończy się po prostu bez instrukcji return, status ostatniego wykonanego polecenia jest zwracany jako kod statusu (i zostanie umieszczony w $?
).
Pamiętaj, zwróć i wyjdź, zwróć kod stanu od 0 do 255, dostępny w $?
. Nie możesz wstawić niczego innego do kodu statusu (np. Zwróć „cat”); to nie zadziała. Ale skrypt może przekazać 255 różnych przyczyn niepowodzenia za pomocą kodów stanu.
Możesz ustawić zmienne zawarte w skrypcie wywołującym lub echo skutkuje funkcją i użyć substytucji poleceń w skrypcie wywołującym; ale celem powrotu i wyjścia jest przekazanie kodów statusu, a nie wartości lub wyników obliczeń, jak można się spodziewać w języku programowania takim jak C.
Czasami uruchamiasz skrypt za pomocą .
lub source
.
. a.sh
Jeśli dodasz exit
do a.sh
niego, nie tylko zakończy on skrypt, ale zakończy sesję powłoki.
Jeśli obejmują return
w a.sh
, po prostu przestaje przetwarzać skrypt.
return: can only 'return' from a function or sourced script
, który sprawia, że nie nadaje się do ogólnego skryptu.
all
sytuacjach. Użycie .
lub source
uruchomienie skryptu w bieżącej powłoce zamiast odradzania podpowłoki. Skrypt musi wiedzieć, jak go używać. Biada użytkownikowi, który robi to odwrotnie. Osobiście polecam przeczytanie skryptów przed uruchomieniem ich po raz pierwszy.
trap
funkcji, ERR EXIT
a następnie najpierw zapisać kod wyjścia nieudanego polecenia, errCode=$?
a następnie wyjść ze skryptu ( źródłowego lub nie), return $errCode || exit $errCode
gdzie ||
oznacza „jeśli nie mogę wrócić, ponieważ nie otrzymałem źródła , po prostu wyjdź zamiast ".
W prostych słowach (głównie dla początkujących w kodowaniu) możemy powiedzieć:
`return` : exits the function,
`exit()` : exits the program(called as process while running)
Również jeśli zauważyłeś, jest to bardzo proste, ale ...
`return` : is the keyword
`exit()` : is the function
exit
nie jest mniej więcej funkcją return
. Są to wbudowane polecenia. Nie są to nawet słowa zastrzeżone.
exit
zakończyć bieżący proces ; z kodem wyjścia lub bez niego, uważaj to za system bardziej niż funkcję programu. Zauważ, że podczas sourcingu exit
zakończy działanie powłoki, jednak po uruchomieniu exit
skryptu.
return
z funkcji wróć do instrukcji po wywołaniu, z kodem powrotu lub bez niego. return
jest opcjonalny i niejawny na końcu funkcji. return
może być używany tylko wewnątrz funkcji.
Chcę dodać, że podczas pozyskiwania exit
skrypt nie jest łatwy do wykonania z poziomu funkcji bez zabicia powłoki. Myślę, że lepszy jest przykład skryptu „testowego”
#!/bin/bash
function die(){
echo ${1:=Something terrible wrong happen}
#... clean your trash
exit 1
}
[ -f /whatever/ ] || die "whatever is not available"
# now we can proceed
echo "continue"
wykonując następujące czynności:
user$ ./test
Whatever is not available
user$
test
i skorupa się zamknie.
user$ . ./test
Whatever is not available
tylko test
zakończy się i pojawi się monit.
Rozwiązaniem jest zawarcie potencjalnie procedury w (
i)
#!/bin/bash
function die(){
echo $(1:=Something terrible wrong happen)
#... clean your trash
exit 1
}
( # added
[ -f /whatever/ ] || die "whatever is not available"
# now we can proceed
echo "continue"
) # added
teraz w obu przypadkach tylko test
wyjdzie.
(
i )
umieszcza ten blok w podpowłoce, skutecznie nie wykonując polecenia .
(źródłowego), tak jakbyś normalnie uruchomił skrypt testowy, który znajduje się w podpowłoce. Jeśli skrypt nie jest uruchamiany z, .
lub source
wtedy efektywnie masz 2 podpowłoki.
Pytanie OP: Jaka jest różnica między instrukcją return i exit w funkcjach BASH w odniesieniu do kodów wyjścia?
Po trzecie, potrzebne jest pewne wyjaśnienie:
Na powyższej liście punktorów wybierz z „(x | y)” albo zawsze pierwszy element, albo zawsze drugi element, aby uzyskać instrukcje dotyczące odpowiednio funkcji i powrotu lub powłok i wyjścia.
Oczywiste jest, że oboje mają wspólne zastosowanie specjalnej zmiennej $? przekazywać wartości w górę po ich zakończeniu.
* Teraz specjalne sposoby, że $? może być ustawiony:
Warto zauważyć, że $? można przypisać wartość, wywołując exit w podpowłoce, tak jak to:
# (exit 259)
# echo $?
3
exit 259
echo, 3
ponieważ końcowa wartość wyjściowa to jeden bajt. 259 % 256 = 3
Przede wszystkim return
jest słowem kluczowym iexit
mój przyjaciel jest funkcją.
To powiedziawszy, oto najprostsze wyjaśnienie.
return
Zwraca wartość z funkcji.
exit
Wychodzi z bieżącej powłoki lub ją opuszcza.
return
słowem kluczowym. Zwrot to znacznie więcej niż tylko kody wyjścia, dlatego porównanie nie jest sprawiedliwe.
exit
też nie return
są „słowami kluczowymi”, ani, jak to nazywa podręcznik bash, „słowami zastrzeżonymi”. Żaden z nich nie jest również „funkcją” w sensie funkcji bash. Oba są wbudowanymi poleceniami w języku bash. (Wywoływana jest standardowa funkcja biblioteki C exit()
, a język programowania C ma słowo zastrzeżone return
, ale nie należy ich mylić z poleceniami bash, mimo że ich semantyka jest dziwnie podobna.)
help <command>
swoją powłokę, aby uzyskać informacje o tym, co zrobi wbudowana powłoka. W twoim przypadkuhelp return
ihelp exit