Bash işlevlerinde dönüş ve çıkış arasındaki fark


429

Bash fonksiyonlarındaki returnve exitifadeleri arasındaki çıkış kodları arasındaki fark nedir ?


55
Protip: help <command>Bir kabuk yerleşiminin ne yapacağına dair bilgi almak için kabuğunuzu yazın. Sizin durumunuzda help returnvehelp exit
SiegeX

Yanıtlar:


318

Gönderen man bashüzerine return [n];

Bir işlevin yürütülmesini durdurmasına ve n ile belirtilen değeri arayana döndürmesine neden olur. N atlanırsa, dönüş durumu işlev gövdesinde yürütülen son komutun durumudur.

... açık exit [n]:

Kabuğun n durumuyla çıkmasına neden olur. N atlanırsa, çıkış durumu yürütülen son komutun durumudur. EXIT üzerinde bir tuzak, kabuk sona ermeden yürütülür.

DÜZENLE:

Soruyu düzenlemenize göre, çıkış kodlarıyla ilgili olarak, çıkış kodlarıyla returnilgisi yoktur. Çıkış kodları işlevler için değil uygulamalar / komut dosyaları için tasarlanmıştır . Bu bakımdan, betiğin çıkış kodunu ayarlayan tek anahtar kelime ( $?kabuk değişkeni kullanılarak çağıran program tarafından yakalanabilen ) exit.

DÜZENLEME 2:

Yönlendiren exitson ifadem bazı yorumlara neden oluyor. Farklılaştırmak için yapıldıreturn ve exitOP'nin anlaşılması için ve aslında, bir program / kabuk betiğinin herhangi bir noktasında exit, betiği çağrı sürecine bir çıkış kodu ile bitirmenin tek yoludur.

Kabukta yürütülen her komut yerel bir "çıkış kodu" oluşturur: $? bu koda değişken ve kullanılabilir if, &&ve koşullu diğer operatörler diğer komutları yürütün.

Bu çıkış kodları (ve $?değişkenin değeri ) her komut yürütme tarafından sıfırlanır.

Bu arada, komut dosyası tarafından yürütülen son komutun çıkış kodu, çağıran işlem tarafından görüldüğü gibi komut dosyasının kendisinin çıkış kodu olarak kullanılır.

Son olarak, fonksiyonlar çağrıldığında çıkış kodlarına göre kabuk komutları olarak işlev görürler. Fonksiyonun çıkış kodu (fonksiyon içinde ) kullanılarak ayarlanır return. Bu nedenle, bir işlevde return 0çalıştırıldığında, işlev yürütmesi sonlanır ve 0 çıkış kodu verir.


10
Tam olarak değil. Her zaman geçerli kabuktan bir değer döndürür. Bir işlevin içinde olup olmamanız önemli değildir.
Diego Sevilla

10
Düzenlemeniz hakkında yorum yapın: Dönüş değerlerini ve çıkış kodlarını karıştırıyor olabilirim, ancak func(){ return 50; };func;echo $?50 yankıları. Yani $?kabuk değişkeni ile sınırlı görünmüyor exit.
lecodesportif

8
" $?En son yürütülen ön plan boru hattının çıkış durumuna genişler." Bu çıkış, kabuktan bir çağrı şeklinde exit(veya komut dosyasının sonuna vurarak) veya returnbir işlev içindeki çağrı şeklinde olabilir .
SiegeX

11
@lecodesportif: $? Geçerli işlem / komut dosyasının , exitbu komut dosyası tarafından yürütülen son komutla veya bunun sonucu ile sınırlıdır . Yani, son komut dosyası satırınız bu işleve çağrı ise ve bu işlev 50 döndürürse, evet, $?sizi çağıran işleme ürettiğiniz 50'dir. Ancak, bununla ilgili olması gerekmez return, çünkü bu geçerli komut dosyasıyla sınırlıdır. Yalnızca bu işlev çağrısı komut dosyasının son cümlesiyse döndürülür. exitancak, betiği her zaman bitirin ve $? çağıran işlem için bu değeri döndürün .
Diego Sevilla

11
-1 satır ile karıştırmak için " returnçıkış kodları ile ilgisi yoktur." Deneme bana bir işlevin dönüş kodu ile bir komut dosyasının çıkış kodu arasında işlevsel bir fark olmadığını söylüyor.
Jack

296

returngeçerli işlevin kapsam dışına çıkmasına exitneden olurken , komut dosyasının çağrıldığı noktada sona ermesine neden olur. İşte bunu açıklamaya yardımcı olacak örnek bir program:

#!/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"

Çıktı

$ ./test.sh
this is retfunc()
We are still here
this is exitfunc()

17
Güzel bir örnek. Ayrıca 1 inç çıkış değerini de gösterebilirsiniz $?.
Diego Sevilla

48
"Retfunc" çağrısından önce "set -e" eklerseniz bu işlevin "Biz hala buradayız" yazmaz.
Michael

4
Ancak, echo fnord | while read x; do exitfunc; done; echo "still here""hala burada" yazdıracaktır. whileBu senaryoda sadece alt kabuktan çıkılmış gibi görünüyor .
tripleee

Yaklaşık bir çözüm, done || exit $?ancak bu çirkin ve tam olarak eşdeğer değildir.
tripleee

2
+1 Eklemek yararlı olabilir: `` `` returngeçerli işlevin veya kaynaklı komut dosyasının kapsam dışına çıkmasına neden olacak '' .
Isaac

56

Kimsenin soruyu tam olarak cevapladığını sanmıyorum çünkü ikisinin nasıl kullanıldığını tarif etmiyorlar. OK Bence çıkış komut dosyasının çağrıldığı yeri öldürdüğünü biliyoruz ve çıkış veya çıkış 0 veya çıkış 7 gibi bir durum atayabilirsiniz. Bu, başka bir komut dosyası vb. Tarafından çağrıldığında komut dosyasının nasıl durmaya zorlandığını belirlemek için kullanılabilir.

çağrıldığında döndür işlevi genellikle 1 veya 0 olmak üzere işlevin davranışını belirtmek için belirtilen değeri döndürür. Örneğin:

    #!/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"
    }

şöyle kontrol et:

    if isdirectory $1; then echo "is directory"; else echo "not a directory"; fi

ya da bunun gibi:

    isdirectory || echo "not a directory"

Bu örnekte, test dizinin bulunup bulunmadığını göstermek için kullanılabilir. Geri dönüşten sonra hiçbir şeyin işlevde yürütülmeyeceğine dikkat edin. 0 doğrudur, ancak yanlış diğer prog dillerinden farklı olarak kabukta 1'dir.

İşlevler hakkında daha fazla bilgi için: http://www.linuxjournal.com/content/return-values-bash-functions

NOT: isdirectory işlevi yalnızca eğitim amaçlıdır. Gerçek bir senaryoda böyle bir seçeneği nasıl yaptığınız olmamalıdır.


3
Ya da sadece test -d $1aynı sonucu elde etmek için kullanın . Asla yapma if <check> return else return. <check>en azından bildiğim tüm dillerde tek başına aynı şeyi yapacaktır.
erikbwork

4
Erik'in söylediği şey hakkında daha açık isdirectory() { [ -d "$1" ]; }olmak için: burada sahip olduğunuzla aynı şekilde davranacaktır: Bir kabuk işlevinin varsayılan dönüş değeri, ister kodunun sonuna ulaşarak, ister returnargümanlarla değil, en son komut.
Charles Duffy

11
Buradaki diğer yorumcular, gerçekten returnifadenin davranışı hakkında konuşurken Mike Q'nun örneğinin stilini eleştiriyorlar . Örneğinin basit olduğu ve üretimde kullanılmayacağı doğrudur. Ama basit, bu yüzden görevini gayet iyi yerine getiriyor. Bunda yanlış bir şey yok.
Mike S

Teşekkürler Mike S, evet kabul ediyorum en basit örnek en iyi çıkış vs dönüş açıklar. Diğer yorumlar kesinlikle geçerlidir ve daha gelişmiş bash kodlayıcıları için düşünülmelidir ;-)
Mike Q

1
Bazıları soru ile tam olarak ilgili olmadığını söyleyebilir, ancak bu soruyu bulmama neden olan problemle ilgili ve cevap verdi. :-)
Jesse Steele

33

Unutmayın, işlevler bir komut dosyasının içindedir ve normalde return ifadesi kullanılarak çağrıldıkları andan itibaren geri döner. Harici bir komut dosyasını çağırmak tamamen başka bir konudur ve komut dosyaları genellikle bir çıkış deyimi ile sona erer.

"BASH fonksiyonlarında return ve exit deyimleri arasında çıkış kodlarına göre" fark çok azdır. Her ikisi de kendi değerlerini değil, bir durum döndürür . Sıfır durumu başarıyı gösterirken, diğer tüm durumlar (1 ila 255) bir hata olduğunu gösterir. Return deyimi, komut dosyasının çağrıldığı yerden geri dönerken, çıkış deyimi tüm komut dosyasını karşılaşıldığı yerden sona erdirir.

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).

İşleviniz herhangi bir döndürme ifadesi olmadan bitiyorsa, yürütülen son komutun durumu durum kodu olarak döndürülür (ve $? ).

Unutmayın, geri dönün ve çıkın 0 ile 255 arasında bir durum kodu verin, $? . Bir durum koduna başka bir şey dolduramazsınız (örneğin, "cat" döndür); çalışmayacak. Ancak, bir komut dosyası durum kodlarını kullanarak 255 farklı hata nedenini geri verebilir.

Arama komut dosyasında yer alan değişkenleri ayarlayabilir veya sonuçların fonksiyonda yankılanması ve arama komut dosyasında komut değiştirme işlevinin kullanılması; ancak dönüş ve çıkışın amacı, C gibi bir programlama dilinde beklenebileceği gibi değerleri veya hesaplama sonuçlarını değil durum kodlarını iletmektir.


25

Bazen, .veya kullanarak bir komut dosyası çalıştırırsınız source.

. a.sh

Bir eklerseniz exitiçinde a.sh, sadece senaryoyu sonlandırmak, ancak kabuk oturumu sona ermez.

Eğer bir eklerseniz returniçinde a.sh, sadece dosyasını işlemeyi durdurur.


1
Ama ben sadece a.sh çalıştırdığımda bir hata alıyorum return: can only 'return' from a function or sourced script, bu da genel bir komut dosyası için uygun değildir.
Peter - Monica'yı

Bir senaryoda en üst düzeyde, ikisi de alldurumlar için uygun değildir . Bir alt kabuğu oluşturmak yerine betiği geçerli kabukta kullanmak .veya sourceçalıştırmak. Betiğin nasıl kullanılacağını bilmesi gerekir. Woe bunu tersine yapan kullanıcıya. Şahsen, ilk çalıştırmadan önce komut dosyalarını okumanızı tavsiye ederim.
Jesse Chisholm

3
Ben rastladım müthiş hile bir kullanmaktır trapiçin işlev ERR EXITve daha sonra ilk başarısız bir komutun çıkış kodu tasarrufu errCode=$?ile senaryoyu (kaynaklı veya değil) çıkmak sonra ve return $errCode || exit $errCodenerede ||ben kaynaklı değildi çünkü döndüremez eğer" yollarla , bunun yerine çıkmanız yeterlidir ".
dragon788

6

Basit bir ifadeyle (esas olarak kodlamadaki yeni başlayanlar için),

`return` : exits the function,
`exit()` : exits the program(called as process while running)

Ayrıca gözlemlediyseniz, bu çok basit ama ...,

`return` : is the keyword
`exit()` : is the function

1
Bir bash betiğinde, exitdaha fazla veya daha az bir işlev değildir return. Bunlar yerleşik komutlardır. Ayrılmış kelimeler bile değiller.
Peter - Monica'yı

6
  • exitmevcut süreci sonlandırmak ; çıkış kodu olsun veya olmasın, bunu bir program işlevinden daha çok bir sistem olarak düşünün. Kaynaklama yaparken exit, kabuğu sonlandırır, ancak çalışırken sadece exitkomut dosyası olacaktır .

  • returnbir fonksiyondan çağrıdan sonra, bir dönüş kodu olsun veya olmasın talimatlara geri dönün. returnisteğe bağlıdır ve işlevin sonunda örtülüdür. returnyalnızca bir işlevin içinde kullanılabilir.

Ben kaynak yaparken exit, kabuk öldürmeden bir fonksiyon içinde komut dosyası için kolay olmadığını eklemek istiyorum . Bence, bir örnek 'test' senaryosunda daha iyi

#!/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"

aşağıdakileri yapıyor:

user$ ./test
Whatever is not available
user$

test -ve- kabuk kapanacak.

user$ . ./test
Whatever is not available

bir tek test bitecek ve istem gösterilecektir.

Çözüm, potansiyel prosedürü (ve)

#!/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

şimdi, her iki durumda da sadece testçıkacaktır.


Ekleme (ve )koyar bir alt kabukta blok etkili un-yapıyor .bir alt kabuk içindedir normalde test komut dosyası çalıştırmak sanki (kaynak) komutu. Komut dosyası ile çalıştırılmazsa .veya sourceetkili bir şekilde 2 alt kabukunuz varsa.
Jesse Chisholm

3

OP'nin sorusu: BASH işlevlerindeki return ve exit deyimleri arasındaki çıkış kodları arasındaki fark nedir?

Açıkçası, bazı açıklamalar gereklidir:

  • Bir (işlev | kabuk) yürütülmesini sonlandırmak için bir (return | exit) ifadesi gerekli değildir. Bir (function | shell) kod listesinin sonuna geldiğinde (return | exit) ifadesi olmasa bile sona erer.
  • Sonlandırılmış (işlev | kabuk) bir değeri geri iletmek için (return | exit) ifadesi gerekli değildir. Her işlem yerleşik bir değişken $? her zaman sayısal bir değere sahiptir. "? = 1" gibi ayarlanamayan, ancak yalnızca özel yollarla ayarlanan özel bir değişkendir (aşağıya bakın *). $ Değeri? (işlev | alt kabuk olarak adlandırılır) içinde çalıştırılacak son komuttan sonra (işlev arayan | üst kabuk) öğesine iletilen değerdir. Yürütülen son komutun ("return [n]" | "exit [n]") ya da plain ("return") ya da çağrılan işlevler kodundaki son komut olan başka bir komut olup olmadığı doğrudur.

Yukarıdaki madde işareti listesinde, sırasıyla işlevler ve dönüş veya kabuklar ve çıkışlar hakkında ifadeler almak için her zaman ilk öğe veya her zaman ikinci öğe arasından "(x | y)" arasından seçim yapın.

Her ikisi de $ özel değişkeninin ortak kullanımını paylaştığı açık mı? değerleri, sona erdikten sonra yukarı doğru iletmek için.

* Şimdi $ özel yolları için? ayarlanabilir:

  • Çağrılan bir işlev sonlandığında ve çağrısına geri döndüğünde $? Arayanda $ son değerine eşit olacak? sonlandırılmış işlevde.
  • Bir üst kabuk dolaylı olarak veya açıkça tek bir alt kabukta beklediğinde ve bu alt kabuğun sonlandırılmasıyla serbest bırakıldığında, $? üst kabuk $ $ nihai değerine eşit olacak? sonlandırılmış alt kabukta.
  • Bazı yerleşik işlevler $? sonuçlarına bağlı olarak. Ama bazıları bilmiyor.
  • Yerleşik işlevler "return" ve "exit". argümanla ve yürütmeyi sonlandırır.

Bu $ dikkat çekmeye değer mi? aşağıdaki gibi bir alt kabukta çıkış çağrılarak bir değer atanabilir:

# (exit 259)
# echo $?
3  

4
Bazılarının exit 259atlaması durumunda 3, son çıkış değeri tek bir bayt olduğu için yankılar . 259 % 256 = 3
Jesse Chisholm

0

Her şeyden önce, returnbir anahtar kelime ve exitarkadaşım bir işlevdir.

Bununla birlikte, burada en basit açıklamalar var.

return Bir işlevden bir değer döndürür.

exit Geçerli kabuktan çıkar veya çıkar.


Pek sayılmaz! Mantıken yanlışsın. Exit, returnbir anahtar kelime iken bir işlevdir . Dönüş, çıkış kodlarından çok daha fazlasıdır, bu yüzden karşılaştırma adil değildir.
Ahmad Awais

Bu konuyu daha açık hale getirmek için düzenledim. Bunu yapmama yardım ettiğin için teşekkürler.
Ahmad Awais

4
Ne "anahtar kelimeler" ne exitde returnbash el kitabı tarafından "ayrılmış kelimeler" dediği gibi. İkisi de bash işlevi anlamında bir "işlev" değildir. Her ikisi de bash lingo'da yerleşik komutlardır . (Orada olup adlı bir C standart kütüphanesi işlevi exit()ve C programlama dili ayrılmış sözcük bulunan return, ancak bu onların semantik merakla benzer olmasına rağmen, bash komutlarıyla karıştırılmamalıdır.)
Peter - Eski Monica
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.