Bir if ifadesi kullanarak çıkış durumunu kontrol etme


256

Belirli bir çıkışı yankılamak için bir if deyiminde çıkış durumunu kontrol etmenin en iyi yolunun ne olacağını merak ediyordum.

Bunun olduğunu düşünüyorum

if [ $? -eq 1 ]
then
   echo "blah blah blah"
fi

Ben de yaşıyorum sorun sadece çünkü bu çıkış kodu olması gerekir, çıkış deyimi if deyimi önce olmasıdır. Ayrıca, çıkış programdan çıkacağı için yanlış bir şey yaptığımı biliyorum.


3
Plaese, betiğinizin tamamını (veya en azından daha geniş bir kapsamı) yayınlar. Yoksa bu iyi görünüyor.
RedX

6
Belirli bir program çağrısından çıkış kodunu iki farklı yerde kullanmanız gerekiyorsa, onu korumanız gerekir - çizgileri boyunca bir şeysome_program; rc=$?; if [ ${rc} -eq 1 ] .... fi ; exit ${rc}
twalberg

Yanıtlar:


263

Çalışan her komutun bir çıkış durumu vardır.

Bu kontrol, o satır çalışmadan önce en son biten komutun çıkış durumuna bakmaktadır.

Bu test true olduğunda (önceki komut başarısız olduğunda) komut dosyanızın çıkmasını istiyorsanız ,exit 1 o ifsatırdan sonra o bloğun içine (veya herhangi bir şeyi) koyarsınız echo.

Komutu çalıştırıyorsanız ve çıktısını aşağıdakileri kullanarak test etmek istiyorsanız, genellikle daha basittir.

if some_command; then
    echo command returned true
else
    echo command returned some error
fi

Ya da bunu !olumsuzlama için kullanmak

if ! some_command; then
    echo command returned some error
else
    echo command returned true
fi

Ancak bunların hiçbirinin hata kodunun ne olduğunu umursamadığını unutmayın . Yalnızca belirli bir hata kodunu önemsediğinizi biliyorsanız, $?manuel olarak kontrol etmeniz gerekir .


11
@ deadcell4 Bir program arızasında bir kabuk betiğini sonlandırmak gerektiğinde, aşağıdaki deyim yararlıdıra_command || return 1
gboffi

10
@gboffi returnyalnızca bir işlev ve kaynaklı bir komut dosyasında çalışır. İhtiyacınız exit(bir fonksiyonu çok fazla yapar ve bir kaynaklı senaryo olan) diğer durum için. Ancak evet, belirli bir temizleme veya ekstra çıktıya ihtiyacınız yoksa kesinlikle makul bir modeldir.
Etan Reisner

1
Söylemeliyim ki dash, birçok modern linux dağıtımında varsayılan etkileşimli olmayan kabuk , yürütülen kabuk komut dosyalarının arasındaki returnve exitiçindeki ayrımı umursamıyor . İçinde dashkullansam bile komut dosyasından çıkar return.
gboffi

Son iki kontrolün arkasındaki mantık nedir? if <command>Çıkış kodu 0 ise koşulun geçmesi sezgisel görünmektedir. Başka bir dilde başka bir yol olurdu
sjw

3
ÖNEMLİ NOT: Bu borular için çalışmaz. if ! some_command | some_other_commandsome_command durumunu yok sayar. En iki komut geçici çözümü set -o pipefail(programınızın diğer bölümlerindeki işlevleri değiştirebilir) veya ififadeyi if [[ ${PIPESTATUS[0]} -ne 0 ]]ayrı bir izleme komutu (çirkin, ancak işlevsel) olarak taşımaktır . Kullanıyorsanız , ikinci çözümü kullanırken borunun sonuna set -eda eklemek istersiniz, || trueçünkü borunun sunduğu kontrol akışından çıkarılması ifaksi takdirde hemen çıkmasına neden olur.
Alex Jansen

186

Hata bildirmek için! = 0 çıkış kodlarının kullanıldığını unutmayın. Yani, yapmak daha iyidir:

retVal=$?
if [ $retVal -ne 0 ]; then
    echo "Error"
fi
exit $retVal

onun yerine

# will fail for error codes > 1
retVal=$?
if [ $retVal -eq 1 ]; then
    echo "Error"
fi
exit $retVal

RetVal üzerinde test yapmalısınız, çünkü $? retVal öğesinin atanmasından sonra komutunuzdaki dönüş değeri olmaz.
anr78

Gerçekten değil: mywiki.wooledge.org/BashFAQ/002 - ancak, düzenlemenin okunabilirliği artırdığını kabul ediyorum.
Oo.oO

1
Bunu açıklayan bu
gönderiyi buldum

dnf check-update0 (güncelleme yok), 100 (güncelleme mevcut) veya 1 (hata) döndürür.
jww

1
@jww - bu, konvansiyona karşı çıkmak için iyi bir fikir değil ( gnu.org/software/bash/manual/html_node/Exit-Status.html ). Ancak, bunu engelleyecek hiçbir şey yok. dnfGeliştiriciler bu yolu seçtiyse , bu onların seçimi. Ama yine de, seçimleri şartnameyi
kırmıyor

44

$?diğeri gibi bir parametredir. Sonunda arama yapmadan önce değerini kullanmak için kaydedebilirsiniz exit.

exit_status=$?
if [ $exit_status -eq 1 ]; then
    echo "blah blah blah"
fi
exit $exit_status

29

Açıklığa alternatif if ifadeye

Minimal:

test $? -eq 0 || echo "something bad happened"

Tamamlayınız:

EXITCODE=$?
test $EXITCODE -eq 0 && echo "something good happened" || echo "something bad happened"; 
exit $EXITCODE

13

Sadece yararlı ve ayrıntılı cevaba eklemek için :

Çıkış kodunu açıkça kontrol etmeniz gerekiyorsa, aritmetik işlecini (( ... ))şu şekilde kullanmak daha iyidir :

run_some_command
(($? != 0)) && { printf '%s\n' "Command exited with non-zero"; exit 1; }

Veya bir caseifade kullanın :

run_some_command; ec=$?  # grab the exit code into a variable so that it can
                         # be reused later, without the fear of being overwritten
case $ec in
    0) ;;
    1) printf '%s\n' "Command exited with non-zero"; exit 1;;
    *) do_something_else;;
esac

Bash'te hata işleme ile ilgili cevap:

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.