Linux'ta Bash Komut Dosyalarında set ve pipefail Nasıl Kullanılır
Yayınlanan: 2022-06-25 Linux set
ve pipefail
komutları, bir Bash betiğinde bir hata oluştuğunda ne olacağını belirler. Durması veya devam etmesinden daha fazla düşünülecek şey var.
İLGİLİ: Kabuk Komut Dosyası Oluşturmaya Yeni Başlayanlar Kılavuzu: Temel Bilgiler
Bash Komut Dosyaları ve Hata Koşulları
Bash kabuk betikleri harikadır. Hızlı yazarlar ve derlemeye ihtiyaçları yoktur. Gerçekleştirmeniz gereken herhangi bir tekrarlayan veya çok aşamalı eylem, uygun bir komut dosyasına sarılabilir. Ve komut dosyaları standart Linux yardımcı programlarından herhangi birini çağırabildiğinden, kabuk dilinin yetenekleriyle sınırlı değilsiniz.
Ancak harici bir yardımcı programı veya programı aradığınızda sorunlar ortaya çıkabilir. Başarısız olursa, harici yardımcı program kapanır ve kabuğa bir dönüş kodu gönderir ve hatta terminale bir hata mesajı yazdırabilir. Ancak komut dosyanız işlemeye devam edecek. Belki de istediğin bu değildi. Komut dosyasının yürütülmesinde erken bir hata oluşursa, komut dosyasının geri kalanının çalışmasına izin verilirse daha kötü sorunlara yol açabilir.
Her bir harici sürecin dönüş kodunu tamamlandıkça kontrol edebilirsiniz, ancak işlemler diğer işlemlere aktarıldığında bu zorlaşır. Dönüş kodu, ortadaki başarısız olandan değil, borunun sonundaki süreçten olacaktır. Elbette, başlatılmamış bir değişkene erişmeye çalışmak gibi betiğinizin içinde de hatalar meydana gelebilir.
set
ve pipefile
komutları, bunun gibi hatalar oluştuğunda ne olacağına karar vermenizi sağlar. Ayrıca, bir boru zincirinin ortasında meydana geldiklerinde bile hataları tespit etmenize izin verirler.
İşte bunları nasıl kullanacağınız.
Sorunu Göstermek
İşte önemsiz bir Bash betiği. Terminale iki satırlık metin yansıtır. Metni bir düzenleyiciye kopyalayıp “script-1.sh” olarak kaydederseniz bu betiği çalıştırabilirsiniz.
#!/bin/bash echo İlk önce bu olacak echo Bu ikinci olacak
Yürütülebilir hale getirmek için chmod
kullanmanız gerekir:
chmod +x script-1.sh
Bilgisayarınızda çalıştırmak istiyorsanız bu komutu her komut dosyasında çalıştırmanız gerekir. Komut dosyasını çalıştıralım:
./script-1.sh
İki satır metin, beklendiği gibi terminal penceresine gönderilir.
Komut dosyasını biraz değiştirelim. ls
var olmayan bir dosyanın ayrıntılarını listelemesini isteyeceğiz. Bu başarısız olacak. Bunu “script-2.sh” olarak kaydettik ve çalıştırılabilir hale getirdik.
#!/bin/bash echo İlk önce bu olacak ls hayali-dosya adı echo Bu ikinci olacak
Bu betiği çalıştırdığımızda ls
gelen hata mesajını görüyoruz.
./script-2.sh
ls
komutu başarısız olmasına rağmen, komut dosyası çalışmaya devam etti. Ve betiğin yürütülmesi sırasında bir hata olmasına rağmen, betiğin kabuğa dönüş kodu sıfırdır, bu da başarıyı gösterir. Bunu echo ve $?
kullanarak kontrol edebiliriz. kabuğa gönderilen son dönüş kodunu tutan değişken.
yankı $?
Raporlanan sıfır, komut dosyasındaki ikinci yankıdan gelen dönüş kodudur. Yani bu senaryoda iki sorun var. Birincisi, betikte bir hata vardı ama çalışmaya devam etti. Komut dosyasının geri kalanı başarısız olan eylemin gerçekten başarılı olmasını bekliyorsa veya buna bağlıysa, bu başka sorunlara yol açabilir. İkincisi, başka bir komut dosyası veya işlemin bu komut dosyasının başarısını veya başarısızlığını kontrol etmesi gerekiyorsa, yanlış bir okuma alacaktır.
set -e Seçeneği
set -e
(çıkış) seçeneği, çağırdığı işlemlerden herhangi biri sıfır olmayan bir dönüş kodu oluşturursa, bir betiğin çıkmasına neden olur. Sıfır olmayan her şey başarısızlık olarak kabul edilir.
Komut dosyasının başına set -e
seçeneğini ekleyerek davranışını değiştirebiliriz. Bu "script-3.sh".
#!/bin/bash -e'yi ayarla echo İlk önce bu olacak ls hayali-dosya adı echo Bu ikinci olacak
Bu betiği çalıştırırsak set -e
etkisini göreceğiz.
./script-3.sh
yankı $?
Komut dosyası durdurulur ve kabuğa gönderilen dönüş kodu sıfır olmayan bir değerdir.
Borulardaki Arızalarla Başa Çıkma
Borulama, soruna daha fazla karmaşıklık katar. Borulu bir komut dizisinden çıkan dönüş kodu, zincirdeki son komuttan gelen dönüş kodudur. Zincirin ortasında bir komutla bir başarısızlık varsa, ilk kareye geri döneriz. Bu dönüş kodu kaybolur ve komut dosyası işlemeye devam eder.
true
ve false
kabuk yerleşiklerini kullanarak farklı dönüş kodlarıyla boru komutlarının etkilerini görebiliriz. Bu iki komut, sırasıyla sıfır veya bir dönüş kodu oluşturmaktan fazlasını yapmaz.
doğru
yankı $?
yanlış
yankı $?
true
false
false
bir süreci temsil eder - true
'nin sıfır dönüş kodunu alırız.
yanlış | doğru
yankı $?
Bash'in PIPESTATUS
adında bir dizi değişkeni vardır ve bu, boru zincirindeki her programdan gelen tüm dönüş kodlarını yakalar.
yanlış | doğru | yanlış | doğru
echo "${PIPESTATUS[0]} ${PIPESTATUS[1]} ${PIPESTATUS[2]} ${PIPESTATUS[3]}"
PIPESTATUS
yalnızca bir sonraki program çalışana kadar dönüş kodlarını tutar ve hangi dönüş kodunun hangi programla gittiğini belirlemeye çalışmak çok hızlı bir şekilde çok dağınık olabilir.
set -o
(seçenekler) ve boru arızası burada devreye girer. Bu, “ pipefail
” dır. Bu, var olmayan bir dosyanın içeriğini wc
içine aktarmaya çalışacaktır.
#!/bin/bash -e'yi ayarla echo İlk önce bu olacak kedi komut dosyası-99.sh | wc -l echo Bu ikinci olacak
Bu, beklediğimiz gibi başarısız olur.
./script-4.sh
yankı $?
İlk sıfır, wc
çıktısıdır ve bize eksik dosya için herhangi bir satır okumadığını söyler. İkinci sıfır, ikinci echo
komutundan gelen dönüş kodudur.
-o pipefail
, onu “script-5.sh” olarak kaydedeceğiz ve çalıştırılabilir hale getireceğiz.
#!/bin/bash set -eo boru arızası echo İlk önce bu olacak kedi komut dosyası-99.sh | wc -l echo Bu ikinci olacak
Bunu çalıştıralım ve dönüş kodunu kontrol edelim.
./script-5.sh
yankı $?
Komut dosyası durur ve ikinci echo
komutu yürütülmez. Kabuğa gönderilen dönüş kodu, bir hata olduğunu doğru bir şekilde gösterir.
İLGİLİ: Linux'ta Echo Komutu Nasıl Kullanılır
Başlatılmamış Değişkenleri Yakalama
Başlatılmamış değişkenleri gerçek dünya komut dosyasında tespit etmek zor olabilir. Başlatılmamış bir değişkenin değerini echo
çalışırsak, echo
yalnızca boş bir satır yazdırır. Hata mesajı vermiyor. Komut dosyasının geri kalanı yürütülmeye devam edecek.
Bu script-6.sh.
#!/bin/bash set -eo boru arızası echo "$notset" echo "Başka bir yankı komutu"
Onu çalıştıracağız ve davranışını gözlemleyeceğiz.
./script-6.sh
yankı $?
Komut dosyası başlatılmamış değişkenin üzerinden geçer ve çalışmaya devam eder. Dönüş kodu sıfırdır. Çok uzun ve karmaşık bir komut dosyasında böyle bir hatayı bulmaya çalışmak çok zor olabilir.
Bu tür bir hatayı set -u
(unset) seçeneğini kullanarak yakalayabiliriz. Bunu, komut dosyasının üst kısmındaki büyüyen set seçenekleri koleksiyonumuza ekleyeceğiz, “script-7.sh” olarak kaydedeceğiz ve yürütülebilir hale getireceğiz.
#!/bin/bash set -eou boru arızası echo "$notset" echo "Başka bir yankı komutu"
Komut dosyasını çalıştıralım:
./script-7.sh
yankı $?
Başlatılmamış değişken algılanır, komut dosyası durur ve dönüş kodu bire ayarlanır.
-u
(unset) seçeneği, başlatılmamış bir değişkenle yasal olarak etkileşime girebileceğiniz durumlar tarafından tetiklenmeyecek kadar akıllıdır.
“script-8.sh” içinde, betik New_Var
değişkeninin başlatılıp başlatılmadığını kontrol eder. Senaryonun burada durmasını istemezsiniz, gerçek dünya senaryosunda daha fazla işlem yapacak ve durumla kendiniz ilgileneceksiniz.
-u
seçeneğini set ifadesine ikinci seçenek olarak eklediğimizi unutmayın. -o pipefail
seçeneği en son gelmelidir.
#!/bin/bash set -euo boru arızası if [ -z "${Yeni_Var:-}" ]; sonra echo "New_Var kendisine atanmış bir değere sahip değil." fi
“script-9.sh” da başlatılmamış değişken test edilir ve başlatılmamışsa bunun yerine varsayılan bir değer sağlanır.
#!/bin/bash set -euo boru arızası default_value=484 Değer=${Yeni_Var:-$varsayılan_değer} echo "New_Var=$Değer"
Komut dosyalarının tamamlanmalarına kadar çalışmasına izin verilir.
./script-8.sh
./script-9.sh
balta ile mühürlü
Kullanılacak başka bir kullanışlı seçenek de set -x
(yürüt ve yazdır) seçeneğidir. Senaryo yazarken, bu bir cankurtaran olabilir. komutları ve parametrelerini yürütüldüklerinde yazdırır.
Size hızlı bir "kaba ve hazır" yürütme izi biçimi sunar. Mantık kusurlarını izole etmek ve hataları tespit etmek çok, çok daha kolay hale geliyor.
“script-8.sh” dosyasına set -x seçeneğini ekleyeceğiz, “script-10.sh” olarak kaydedeceğiz ve çalıştırılabilir hale getireceğiz.
#!/bin/bash set -euxo boru arızası if [ -z "${Yeni_Var:-}" ]; sonra echo "New_Var kendisine atanmış bir değere sahip değil." fi
İz çizgilerini görmek için çalıştırın.
./script-10.sh
Bu önemsiz örnek komut dosyalarındaki hataları tespit etmek kolaydır. Daha ilgili komut dosyaları yazmaya başladığınızda, bu seçenekler değerlerini kanıtlayacaktır.