Hata Üzerine Bir Komut Dosyasından Çıkma


141

Bunun ifgibi bir işlevi olan bir kabuk komut dosyası oluşturuyorum :

if jarsigner -verbose -keystore $keyst -keystore $pass $jar_file $kalias
then
    echo $jar_file signed sucessfully
else
    echo ERROR: Failed to sign $jar_file. Please recheck the variables
fi

...

Hata iletisini görüntüledikten sonra komut dosyasının yürütülmesini bitirmek istiyorum. Bunu nasıl yapabilirim?

Yanıtlar:


137

Arıyorsunuz exit?

Bu en iyi bash kılavuzdur. http://tldp.org/LDP/abs/html/

Bağlamda:

if jarsigner -verbose -keystore $keyst -keystore $pass $jar_file $kalias
then
    echo $jar_file signed sucessfully
else
    echo ERROR: Failed to sign $jar_file. Please recheck the variables 1>&2
    exit 1 # terminate and indicate error
fi

...


Bu Bash bağlantıları KORKUNÇ! BashFAQ, BashRecipes olarak daha iyi konumlandırılacaktır.
Pete Alvin

337

Eğer koyarsan set -eBir komut dosyası , komut dosyası içindeki herhangi bir komut başarısız olursa (yani herhangi bir komut sıfır dışında bir durum döndürdüğünde) sonlandırılır. Bu, kendi mesajınızı yazmanıza izin vermez, ancak genellikle başarısız olan komutun kendi mesajları yeterlidir.

Bu yaklaşımın avantajı otomatik olmasıdır: bir hata durumuyla başa çıkmayı unutma riski taşımıyorsunuz.

Olan durumu (örneğin, bir koşullu ile test edilir komutlar if, &&ya da ||) komut sonlanamayan (aksi şartlı anlamsız olacaktır). Başarısızlığı önemli olmayan ara sıra komut için bir deyim command-that-may-fail || true. Ayrıca set -ekomut dosyasının bir kısmı için ile kapatabilirsiniz set +e.


3
Mywiki.wooledge.org/BashFAQ/105'e göre - bu özellik, hangi komutların hata kodlarının otomatik çıkışa neden olduğuna karar verirken belirsiz ve kıvrık bir geçmişe sahiptir. Ayrıca, "Bash bu 'özelliğin' son derece kaygan POSIX tanımını izlemeye çalıştıkça, kurallar bir Bash versiyonundan diğerine değişir". @Dennis Williamson ve stackoverflow.com/questions/19622198/… ' in kabul edilen cevabına katılıyorum -' error_handler 'ERR tuzağını kullan. Bu bir tuzak olsa bile!
Bondolin

3
genellikle -xbayrağı bayrakla kullanmak, -eprogramınızın çıkışta olduğu yerde bir iz bırakmanız yeterlidir. Bu, komut dosyasının kullanıcısının aynı zamanda geliştirici olduğunu ima eder.
Alex

Güzel ama OP'nin senaryoyu kendinden tanımlı bir istisnadan çıkarması gerektiğini düşünüyorum.
vdegenne

42

Körü körüne çıkmak yerine hatayı kullanmak yerine bir hatayı işlemek istiyorsanız , sözde sinyalde set -ea kullanın .trapERR

#!/bin/bash
f () {
    errorCode=$? # save the exit code as the first thing done in the trap function
    echo "error $errorCode"
    echo "the command executing at the time of the error was"
    echo "$BASH_COMMAND"
    echo "on line ${BASH_LINENO[0]}"
    # do some error handling, cleanup, logging, notification
    # $BASH_COMMAND contains the command that was being executed at the time of the trap
    # ${BASH_LINENO[0]} contains the line number in the script of that command
    # exit the script or return to try again, etc.
    exit $errorCode  # or use some other value or do return instead
}
trap f ERR
# do some stuff
false # returns 1 so it triggers the trap
# maybe do some other stuff

Diğer tuzaklar, normal Unix sinyalleri artı diğer Bash sözde sinyalleri RETURNve dahil olmak üzere diğer sinyalleri işlemek için ayarlanabilir DEBUG.


8

İşte bunu yapmanın yolu:

#!/bin/sh

abort()
{
    echo >&2 '
***************
*** ABORTED ***
***************
'
    echo "An error occurred. Exiting..." >&2
    exit 1
}

trap 'abort' 0

set -e

# Add your script below....
# If an error occurs, the abort() function will be called.
#----------------------------------------------------------
# ===> Your script goes here
# Done!
trap : 0

echo >&2 '
************
*** DONE *** 
************
'

Stderr'a neden YAPILDI mesajı?
MattBianco

1
Bu yaygın bir uygulamadır, böylelikle komut dosyası çıktısını stdout'a yönlendirebilirsiniz, böylece başka bir işlem ortada bilgi mesajları olmadan alabilir.
supercobra

2
Stderr'deki herhangi bir şeyi problemlerin bir göstergesi olarak tedavi etmek muhtemelen eşit derecede yaygın bir uygulamadır.
MattBianco

1
Geçmişte 'set -e' her zaman benim için çalıştı, ama bu gece Alpine Linux Docker görüntüsünde hiçbir etkisi olmayan bir durumla karşılaştım. Bu çözüm benim için çalıştı ve eldeki işe geri döndü. Çok takdir etmek.
synthesizerpatel

@supercobra Ortak uygulama? Nerede?
Thorbjørn Ravn Andersen

-8

exit 1tüm ihtiyacın olan. Bu 1bir dönüş kodudur, yani 1başarılı bir çalışma -1demek ve başarısızlık ya da bunun gibi bir şey demek istiyorsanız değiştirebilirsiniz .


13
Unix'te başarı her zaman 0'dır. Bu, testveya kullanılırken yardımcı olabilir&& veya|| .
mouviciel

5
Mouviciel'in yorumunu genişletmek için: kabuk komut dosyalarında 0 her zaman başarı demektir ve 1 ila 255 başarısızlık demektir. -1 aralık dışında (ve genellikle 255 ile aynı etkiye sahip olacak, bu nedenle 1 gibi bir hata).
Gilles 'SO- şeytan olmayı bırak'

@mouviciel, @Gilles: Ek bilgi için teşekkürler. Ben bash ile uğraştığımdan bu yana bir süre geçti.
DGH

Bu, dönüş kodu kullanımının kötü bir örneğidir, aksi takdirde harika bir yanıt olacaktır.
Brad Koch

1
Başarısız bir şekilde 1'i başarılı bir şekilde önermenin yanı sıra -1 mümkün değildir (çıkış kodları imzalanmamıştır).
tripleee
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.