Linux'ta Bash Komut Dosyalarında Hatalar Nasıl Yakalanır

Yayınlanan: 2022-08-27
Bir bash istemi gösteren Linux dizüstü bilgisayar
fatmawati achmad zaenuri/Shutterstock.com

Varsayılan olarak, Linux'ta bir Bash betiği bir hata bildirir ancak çalışmaya devam eder. Daha sonra ne olması gerektiğine karar verebilmeniz için hataları kendiniz nasıl ele alacağınızı gösteriyoruz.

Komut Dosyalarında Hata İşleme

Hataları işleme, programlamanın bir parçasıdır. Kusursuz kod yazsanız bile, yine de hata koşullarıyla karşılaşabilirsiniz. Siz yazılım yükledikçe ve kaldırdıkça, dizinler oluşturdukça ve yükseltme ve güncellemeler yaptıkça bilgisayarınızdaki ortam zamanla değişir.

PowerShell'de Parametre Doğrulama Hatalarını Özelleştirme
İLGİLİ PowerShell'de Parametre Doğrulama Hatalarını Özelleştirme

Örneğin, önceden sorunsuz çalışan bir komut dosyası, dizin yolları değişirse veya bir dosyadaki izinler değiştirilirse zorluklarla karşılaşabilir. Bash kabuğunun varsayılan eylemi, bir hata mesajı yazdırmak ve komut dosyasını yürütmeye devam etmektir. Bu tehlikeli bir varsayılandır.

Başarısız olan eylem, komut dosyanızda daha sonra gerçekleşecek başka bir işlem veya eylem için kritikse, bu kritik eylem başarılı olmayacaktır. Bunun ne kadar feci olduğu, senaryonuzun ne yapmaya çalıştığına bağlıdır.

Daha sağlam bir şema, hataları tespit eder ve komut dosyasının kapatılması veya arıza durumunu düzeltmeye çalışması gerektiğinde çalışmasına izin verir. Örneğin, bir dizin veya dosya eksikse, komut dosyasının bunları yeniden oluşturması tatmin edici olabilir.

Komut dosyası kurtarılamayan bir sorunla karşılaşırsa kapatılabilir. Komut dosyasının kapatılması gerekiyorsa, geçici dosyaları kaldırmak veya hata durumunu ve kapatma nedenini bir günlük dosyasına yazmak gibi gerekli temizleme işlemlerini gerçekleştirme şansına sahip olabilir.

Çıkış Durumunu Algılama

Komutlar ve programlar, sonlandırıldıklarında işletim sistemine gönderilen bir değer oluşturur. Buna çıkış durumları denir. Hata yoksa sıfır, bir hata oluştuysa sıfır olmayan bir değere sahiptir.

Komut dosyasının kullandığı komutların çıkış durumunu (dönüş kodu olarak da bilinir) kontrol edebilir ve komutun başarılı olup olmadığını belirleyebiliriz.

Bash'de sıfır, true değerine eşittir. Komuttan gelen yanıt doğru dışında bir şeyse, bir sorun olduğunu biliyoruz ve uygun eylemi yapabiliriz.

Bu komut dosyasını bir düzenleyiciye kopyalayın ve “bad_command.sh” adlı bir dosyaya kaydedin.

 #!/bin/bash

if ( ! bad_command ); sonra
  echo "bad_command bir hata işaretledi."
  çıkış 1
fi

Komut dosyasını chmod komutuyla yürütülebilir hale getirmeniz gerekir. Bu, herhangi bir komut dosyasını yürütülebilir hale getirmek için gerekli bir adımdır, bu nedenle komut dosyalarını kendi makinenizde denemek istiyorsanız, bunu her biri için yapmayı unutmayın. Her durumda uygun komut dosyasının adını değiştirin.

 chmod +x bad_command.sh 

chmod kullanarak bir komut dosyasını yürütülebilir hale getirme

Komut dosyasını çalıştırdığımızda beklenen hata mesajını görüyoruz.

 ./bad_command.sh 

Bir hata olup olmadığını belirlemek için bir komutun çıkış durumunu kontrol etme

“bad_command” diye bir komut yok, betik içindeki bir fonksiyonun adı da yok. Yürütülemez, bu nedenle yanıt sıfır değildir . Yanıt sıfır değilse—burada ünlem işareti mantıksal NOT operatörü olarak kullanılır— if ifadesinin gövdesi yürütülür.

Gerçek dünyadaki bir komut dosyasında bu, örneğimizin yaptığı gibi komut dosyasını sonlandırabilir veya hata durumunu düzeltmeye çalışabilir.

exit 1 satırı gereksiz gibi görünebilir. Sonuçta, senaryoda başka bir şey yok ve yine de sona erecek. Ancak exit komutunu kullanmak, bir çıkış durumunu kabuğa geri iletmemizi sağlar. Komut dosyamız ikinci bir komut dosyası içinden çağrılırsa, o ikinci komut dosyası bu komut dosyasının hatalarla karşılaştığını bilir.

Bir komutun çıkış durumuyla mantıksal OR operatörünü kullanabilir ve ilk komuttan sıfır olmayan bir yanıt varsa betiğinizde başka bir komut veya işlev çağırabilirsiniz.

 komut_1 || komut_2

Bu, ilk komutun OR ikincisinin çalıştırılması nedeniyle çalışır. En soldaki komut önce çalıştırılır. Başarılı olursa, ikinci komut yürütülmez. Ancak ilk komut başarısız olursa, ikinci komut yürütülür. Böylece kodu şu şekilde yapılandırabiliriz. Bu "mantıksal-or./sh."

 #!/bin/bash

error_handler()
{
  echo "Hata: ($?) $1"
  çıkış 1
}

kötü_komut || error_handler "bad_command başarısız oldu, Satır: ${LINENO}"

error_handler adında bir fonksiyon tanımladık. Bu, $? değişkeninde tutulan başarısız komutun çıkış durumunu yazdırır. ve işlev çağrıldığında kendisine iletilen bir metin satırı. Bu, $1 değişkeninde tutulur. İşlev, komut dosyasını bir çıkış durumuyla sonlandırır.

Komut dosyası, açıkça başarısız olan bad_command çalıştırmayı dener, bu nedenle mantıksal OR operatörünün sağındaki komut, || , Idam edildi. Bu, error_handler işlevini çağırır ve başarısız olan komutu adlandıran ve başarısız olan komutun satır numarasını içeren bir dize iletir.

Hata işleyici mesajını görmek için betiği çalıştıracağız ve ardından echo kullanarak betiğin çıkış durumunu kontrol edeceğiz.

 ./mantıksal-or.sh
 yankı $? 

Bir komut dosyasında hata işleyiciyi çağırmak için mantıksal VEYA operatörünü kullanma

Küçük error_handler işlevimiz, bad_command çalıştırma girişiminin çıkış durumunu, komutun adını ve satır numarasını sağlar. Bu, bir komut dosyasında hata ayıklarken yararlı bilgilerdir.

Komut dosyasının çıkış durumu birdir. error_handler tarafından bildirilen 127 çıkış durumu "komut bulunamadı" anlamına gelir. İstesek bunu exit komutuna geçirerek betiğin çıkış durumu olarak kullanabiliriz.

Başka bir yaklaşım, çıkış durumunun farklı olası değerlerini kontrol etmek ve bu tür yapıyı kullanarak buna göre farklı eylemler gerçekleştirmek için error_handler genişletmek olacaktır:

 çıkış_kodu=$?

if [ $exit_code -eq 1 ]; sonra
  echo "İşletime izin verilmiyor"

elif [ $exit_code -eq 2 ]; sonra
  echo "Kabuk yerleşiklerinin kötüye kullanılması"
.
.
.
elif [ $durum -eq 128 ]; sonra
  echo "Geçersiz argüman"
fi

Bir Çıkışı Zorlamak İçin Seti Kullanma

Bir hata olduğunda betiğinizin çıkmasını istediğinizi biliyorsanız, bunu yapmaya zorlayabilirsiniz. bu, herhangi bir temizleme veya daha fazla hasar olasılığını da ortadan kaldırdığınız anlamına gelir, çünkü komut dosyanız bir hata algıladığı anda sona erer.

Bunu yapmak için -e (hata) seçeneği ile set komutunu kullanın. Bu, komut dosyasına bir komut başarısız olduğunda çıkmasını söyler veya sıfırdan büyük bir çıkış kodu döndürür. Ayrıca -E seçeneğinin kullanılması, kabuk işlevlerinde hata algılama ve yakalama çalışmalarını sağlar.

Linux'ta Bash Komut Dosyalarında set ve pipefail Nasıl Kullanılır
İLGİLİ Linux'ta Bash Komut Dosyalarında set ve pipefail Nasıl Kullanılır

Başlatılmamış değişkenleri de yakalamak için -u (unset) seçeneğini ekleyin. Borulu dizilerde hataların algılandığından emin olmak için -o pipefail seçeneğini ekleyin. Bu olmadan, sıralı komut dizisinin çıkış durumu, dizideki son komutun çıkış durumudur. Borulu sıranın ortasındaki başarısız bir komut algılanmayacaktır. -o pipefail seçeneği, seçenekler listesinde gelmelidir.

Komut dosyanızın en üstüne eklenecek sıra:

 set -Eeuo boru arızası

İşte içinde unset-var.sh olan ve içinde unset değişkeni olan kısa bir betik.

 #!/bin/bash

set -Eeou boru arızası

echo "$unset_variable"

echo "Bu satırı görüyor muyuz?"

Komut dosyasını çalıştırdığımızda, unset_variable başlatılmamış bir değişken olarak tanınır ve komut dosyası sonlandırılır.

 ./unset-var.sh 

Bir hata oluşursa komut dosyasını sonlandırmak için komut dosyasında set komutunu kullanma

İkinci echo komutu hiçbir zaman yürütülmez.

Hatalı Tuzağı Kullanma

Bash trap komutu, belirli bir sinyal yükseldiğinde çağrılması gereken bir komutu veya işlevi atamanıza olanak tanır. Tipik olarak bu, Ctrl+C tuş bileşimine bastığınızda ortaya çıkan SIGINT gibi sinyalleri yakalamak için kullanılır. Bu komut dosyası "sigint.sh."

 #!/bin/bash

trap "echo -e '\nCtrl+c' ile sonlandırıldı; çıkış" SIGINT

sayaç=0

doğru iken
yapmak 
  echo "Döngü numarası:" $((++sayaç))
  uyku 1
tamamlamak

trap komutu bir echo komutu ve exit komutu içerir. SIGINT yükseltildiğinde tetiklenecektir. Komut dosyasının geri kalanı basit bir döngüdür. Komut dosyasını çalıştırır ve Ctrl+C'ye basarsanız, trap tanımından gelen mesajı görürsünüz ve komut dosyası sonlandırılır.

 ./sigint.sh 

Ctrl+c'yi yakalamak için bir komut dosyasında tuzak kullanma

Hataları oluştukları anda yakalamak için ERR sinyali ile trap kullanabiliriz. Bunlar daha sonra bir komuta veya işleve beslenebilir. Bu "trap.sh." error_handler adlı bir işleve hata bildirimleri gönderiyoruz.

 #!/bin/bash

tuzak 'error_handler $? $LINENO' HATA

error_handler() {
  echo "Hata: ($1) $2'da oluştu"
}

ana() {
  echo "Main() fonksiyonunun içinde"
  bad_command
  ikinci
  üçüncü
  $ çıkış?
}

ikinci() {
  echo "Main() çağrısından sonra"
  echo "İkinci () işlevinde"
}

üçüncü() {
  echo "Üçüncü() işlevin içinde"
}

ana

Komut dosyasının büyük kısmı, second ve third işlevleri çağıran main işlevin içindedir. Bir hatayla karşılaşıldığında - bu durumda, bad_command olmadığı için - trap ifadesi hatayı error_handler işlevine yönlendirir. Başarısız komuttan çıkış durumunu ve satır numarasını error_handler işlevine iletir.

 ./trap.sh 

Bir komut dosyasındaki hataları yakalamak için ERR ile tuzak kullanma

error_handler işlevimiz, hatanın ayrıntılarını terminal penceresine listeler. İsterseniz, komut dosyasının sonlandırılması için işleve bir exit komutu ekleyebilirsiniz. Veya farklı hatalar için farklı eylemler gerçekleştirmek için bir dizi if/elif/fi deyimi kullanabilirsiniz.

Bazı hataları düzeltmek mümkün olabilir, diğerleri komut dosyasının durmasını gerektirebilir.

Son Bir İpucu

Hataları yakalamak, genellikle yanlış gidebilecek şeyleri önceden almak ve ortaya çıkması durumunda bu olasılıkları ele almak için kod koymak anlamına gelir. Bu, betiğinizin yürütme akışının ve dahili mantığının doğru olduğundan emin olmanın yanı sıra.

Komut dosyanızı çalıştırmak için bu komutu kullanırsanız, Bash komut dosyası yürütülürken size bir izleme çıktısı gösterecektir:

 bash -x komut dosyanız.sh

Bash, izleme çıktısını terminal penceresinde yazar. Her komutu bağımsız değişkenleriyle birlikte gösterir - varsa. Bu, komutlar genişletildikten sonra ancak yürütülmeden önce olur.

Bu, anlaşılması zor hataların izlenmesinde muazzam bir yardım olabilir.

İLGİLİ: Çalıştırmadan Önce Linux Bash Komut Dosyasının Sözdizimini Doğrulama