Bash betiğinden çıkmanın, ancak terminalden çıkmamanın herhangi bir yolu


183

Bir exitkabuk komut dosyasında komut kullandığımda, komut dosyası terminali (istemi) sonlandıracaktır. Bir betiği sonlandırıp terminalde kalmanın bir yolu var mı?

Komut run.shdosyamın doğrudan başka bir komut dosyasından veya başka bir komut dosyasından kaynaklanarak yürütülmesi bekleniyor.

DÜZENLEME: Daha spesifik olmak gerekirse, iki komut vardır run2.sholarak

...
. run.sh
echo "place A"
...

ve run.sholarak

...
exit
...

Ben koşmak zaman . run2.sh, ve eğer o exitcodeline vurmak run.sh, ben terminal durdurmak ve orada kalmak istiyorum. Ama kullanarak exit, tüm terminal kapanır.

PS: Kullanmaya çalıştım return, ama echocodeline hala idam edilecek ....


5
Gerçekten, gerçekten, gerçekten sormalıyım: Neden çıkışlı bir senaryoda çıkış kullanıyorsunuz?
Ignacio Vazquez-Abrams

3
çıkış komutu terminal oturumunuzu / girişinizi sonlandırmamalıdır. exit 0başarılı olduktan sonra komut dosyasını sonlandırmak için kullanırsanız , komut dosyanızı ex çalıştırdığınızda: ./test.shçıktıyı görmelisiniz, ancak konsolunuz açık kalacaktır.
Ben Ashton

shellAslında bir kabuk terminali açan komutu kullanabilirsiniz . Benim kendi deneyimim bunun gerçekleşmediğidir exit. Çıkış normal olarak üst betiğe denetimi geri verir.
Willem Van Onsem

Yanıtlar:


258

"Sorun" gerçekten kaynak ve senaryo yürütmüyor olmasıdır. Bir dosyayı kaynak yaptığınızda, içeriği alt kabuk oluşturmak yerine geçerli kabukta yürütülür. Dolayısıyla, çıkış dahil her şey mevcut kabuğu etkiler.

Kullanmak yerine kullanmak exitisteyeceksiniz return.


2
İşte yararlı bulduğum başka bir açıklama: askubuntu.com/a/53179/148337
3cheesewheel

Doğru olmasına rağmen, bu harika bir cevap değil. Çağıran komut dosyasının, komut dosyası olarak adlandırılan değişkenlerin veya işlevlerin erişmesi gerektiğini bildirebileceğini yoksayar. Bir dönüş kodunun nasıl ayarlanacağını ve runs.sh@ruakh içinde nasıl işleneceğini açıklamak daha iyi bu soruya daha iyi bir cevap var.
MikeSchinkel

5
İşlev iç içe bir çağrı ise ne olur? yani bir çağrı b, b çağrı c, c a ve b'den hemen çıkmak istiyor.
Michael

Kaynak neredeyse kopyala yapıştır ile aynı. Kullanmak daha iyi sh <script>veya bash <script>bir senaryo çalıştırmak ve bir noktada sona
ermek istiyorsa

42

Evet; returnyerine kullanabilirsiniz exit. Ana amacı bir kabuk işlevinden geri dönmek, ancak bunu source-d komut dosyasında kullanırsanız, bu komut dosyasından geri döner.

As içinde §4.1 "betiklerin çıkmasını" Bash koyar o:

     return [n]

N döndürme değeriyle çıkmak için kabuk işlevine neden olur . Eğer n sağlanmazsa, dönüş değeri fonksiyonunda son çalıştırılan komutun çıkış durumudur. Bu aynı zamanda .(veya source) yerleşimi ile yürütülen bir komut dosyasının yürütülmesini sonlandırmak için, komut dosyasında komut dosyasının çıkış durumu olarak n veya yürütülen son komutun çıkış durumunu döndürmek için de kullanılabilir. Tuzakla ilişkili herhangi bir komut RETURN, işlev veya komut dosyasından sonra yürütme devam etmeden önce yürütülür. returnBir komut dosyasının .veya tarafından yürütülmesi sırasında işlev dışında kullanılırsa dönüş durumu sıfırdan farklıdır source.


3
returnSADECE bir işlevden kullanılabilir. returnBir kabuk komut dosyası olarak kullanır ve yürütürseniz (örn. sh run.sh) Bash, return: can only bir işlevden veya kaynaklı komut dosyasından bir hata - dönüş 'bildirecektir
Tzunghsing David Wong

@TzungsingDavidWong: Bu cevabın büyük bölümünün resmi referans kılavuzundan bir teklif olduğunu biliyor musunuz? Ve alıntıladığınız hata mesajının talebiniz yerine bu cevaba uyduğunu?
ruakh

Sana katılmıyorum. Ben sadece returnkomut dosyası bir kabuk komut dosyası olarak çalıştırılır ve tarafından yürütülmez ise işe yaramaz işaret etmek istiyorum . (veya source). BTW, belgeyi nereden bulabilirim source -d?
Tzunghsing David Wong

9

Bunun yerine kullanarak alfabenin çalışan . run2.sh, kullanmakta çalıştırabilirsiniz sh run2.shveyabash run2.sh

Komut dosyasını çalıştırmak için yeni bir alt kabuk başlatılacak ve komut dosyasının sonunda diğer kabuğu açılmış olarak kapatılacaktır.


Eğer öyleyse, neden ikinci parametre sh "." run2.sh?
CHAN

@ H0WARD Haklısın Noktaları kaldırmayı unuttum. Cevabı şimdi düzenledim.
Viorel Mirea

1
OP, kaynağı açıkça bir gereklilik olarak belirtir.
Jonathan Neufeld

4

Return deyimi / komutundan sonra komut dosyasının komut satırından yürütülmesi ve terminalden kaynak alınması için her ikisinde de çalışabilmesi için ekstra bir çıkış komutu ekleyebilirsiniz.

Koddaki örnek çıkış kodu:

   if [ $# -lt 2 ]; then
     echo "Needs at least two arguments"
     return 1 2>/dev/null
     exit 1
   fi

exitKomuttan sonra returnkomut dosyasını kaynak yaptığınızda komut içeren satır çağrılmaz .

returnKomut dosyasını yürüttüğünüzde, komut bir hata verir. Bu nedenle, hata iletisini adresine ileterek bastırıyoruz /dev/null.


3

Aslında, nasıl bağırdığınla şaşkın olabileceğini düşünüyorum run a script.

shBir komut dosyası çalıştırmak için kullanırsanız , diyelim ki, sh ./run2.shkatıştırılmış komut dosyası bitse bile exit, terminal pencereniz hala kalır.

Ancak .veya kullanırsanız source, abonelik sona erdiğinde terminal pencereniz de kapanır / kapanır.

daha fazla ayrıntı için lütfen ve ile arasındaki fark nedir ? bölümüne bakın.shsource


2

Bu, run2.sh betiğinizin içine bir run fonksiyonu koyduğunuz gibidir. Run içindeki çıkış kodunu kullanırsanız, run2.sh dosyanızı bash tty'de kaynaklayın. Çalıştırma komut dosyasından çıkma gücünü verir ve run2.sh komutuna sonlandırıcıdan çıkma gücünü verir. Daha sonra çalışma işlevinden teminatordan çıkma gücü vardır.

    #! /bin/sh
    # use . run2.sh

    run()
    {
        echo "this is run"
        #return 0
        exit 0
    }

    echo "this is begin"
    run
    echo "this is end"

Her neyse, Kaz ile bir tasarım sorunu olduğunu onaylıyorum.


Bu cevabın ne yapmaya çalıştığını metinden net değil, ama kesinlikle eldeki soruyu çözmüyor.
Luís de Sousa

2

Aynı sorunu yaşadım ve yukarıdaki cevaplardan ve benim için neyin işe yaradığını anladığımdan:

  1. Örneğin, istenen senaryoyu çağıran bir shebang satırına sahip olun, örneğin,

    #!/bin/bashbashkomut dosyasını yürütmek için kullanır

Ben her iki türden's ile senaryolar var. Bu nedenle, yanlış yürütmeye neden olduğu için shveya kullanmak .güvenilir değildi (komut dosyasının eksik çalışmayı kestiğinde olduğu gibi)

Bu nedenle cevap,

    • Komut dosyasının bir çeteye sahip olduğundan emin olun, böylece amaçlanan işleyicisi hakkında şüphe yoktur.
    • ch .sh dosyasını çalıştırılabilir. (chmod +x file.sh)
    • Doğrudan olmadan çağırın shveya.

      (./myscript.sh)

Umarım bu benzer soru veya problemi olan birine yardımcı olur.


1

Bunun olduğunu düşünüyorum çünkü nokta ile kaynak modunda çalıştırıyorsunuz

. myscript.sh

Bunu bir alt kabukta çalıştırmalısınız:

/full/path/to/script/myscript.sh

'kaynak' http://ss64.com/bash/source.html


. myscript.shÇalışıyorsa komut dosyasının tam yoluna ihtiyacınız yoktur . En fazla ihtiyacınız olabilir ./myscript.sh.
Álvaro González

1

Kaynaklı ve yürütülen komut dosyalarının diğerlerinin de belirttiği gibi aynı oturumu açık tutmak için returnvs. kullanması doğrudur exit.

Aşağıda, kaynaklı olup olmadığına bakılmaksızın, oturumu açık tutması gereken bir komut dosyası istiyorsanız, ilgili bir ipucu.

Aşağıdaki örnek doğrudan / gibi çalıştırılabilir foo.shveya . foo.sh/ gibi kaynaklanabilir source foo.sh. Her iki durumda da "çıktıktan" sonra oturumu açık tutacaktır. $@Dize işlevi dış komut dosyasının argümanları erişebilecek şekilde geçirilir.

#!/bin/sh
foo(){
    read -p "Would you like to XYZ? (Y/N): " response;
    [ $response != 'y' ] && return 1;
    echo "XYZ complete (args $@).";
    return 0;
    echo "This line will never execute.";
}
foo "$@";

Terminal sonucu:

$ foo.sh
$ XYZ ister misiniz? (E / H): n
$. foo.sh
$ XYZ ister misiniz? (E / H): n
$ |
(terminal penceresi açık kalır ve ek girişi kabul eder)

Bu, çalışma sırasında ana exit/ altında bir grup hurda kodu tutarken tek bir terminalde komut dosyası değişikliklerini hızlı bir şekilde test etmek için yararlı olabilir return. Ayrıca, kodu bir anlamda daha taşınabilir hale getirebilir (farklı şekillerde çağrılabilecek veya çağrılamayabilecek tonlarca komut dosyanız varsa), ancak yalnızca returnve exitdaha uygun yerlerde kullanmak daha az karmaşıktır .


0

terminal öykünücünüz yoksa -hold, kaynaklı bir komut dosyasını temizleyebilir ve terminali aşağıdakilerle birlikte tutabilirsiniz:

#!/bin/sh
sed "s/exit/return/g" script >/tmp/script
. /tmp/script
read

aksi takdirde kullanabilirsiniz $TERM -hold -e script


0

Ayrıca beklenen dönüş değeri ile döndüğünüzden emin olun. Başka bir çıkışla karşılaştığınızda exit komutunu kullanırsanız, kaynak başka bir işlem (örnek) oluşturmadığından, temel kabuğunuzdan çıkacaktır.


0

Ya bir kabuk komut dosyası olarak çalıştırmak veya bir rc dosyası olarak temin edilmesi güvenli bir senaryo yazmak için komut kontrol edip karşılaştırabilirsiniz $0ve $BASH_SOURCEve belirlemek exitgüvenle kullanılabilir.

İşte bunun için bir kısa kod snippet'i

[ "X$(basename $0)" = "X$(basename $BASH_SOURCE)" ] && \
    echo "***** executing $name_src as a shell script *****" || \
    echo "..... sourcing $name_src ....."

-1

1) çıkış 0 başarılı olursa komut dosyasından çıkar.

2) çıkış 1 bir hata ise komut dosyasından çıkacaktır.

Ur req dayalı iki yukarıda deneyebilirsiniz.

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.