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

Yayınlanan: 2022-06-25
Mavi bir arka plan üzerinde bir dizüstü bilgisayar ekranında Linux terminali.
fatmawati achmad zaenuri/Shutterstock.com

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.

Bash Kabuğu Nedir ve Linux için Neden Bu Kadar Önemlidir?
İLGİLİ Bash Kabuğu Nedir ve Linux için Neden Bu Kadar Önemlidir?

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 

Hatasız basit bir komut dosyası çalıştırma.

İ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 

Bir komut dosyası çalıştırma ve bir başarısızlık koşulu oluşturma.

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ı $? 

Yürütülen son komut dosyası için dönüş kodu kontrol ediliyor.

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ı $? 

Bir hata koşulunda bir komut dosyasını sonlandırma ve dönüş kodunu doğru şekilde ayarlama.

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ı $? 

Bash kabuğu true ve false yerleşik komutları.

true false false bir süreci temsil eder - true 'nin sıfır dönüş kodunu alırız.

 yanlış | doğru
 yankı $? 

Yanlışı doğruya çevirmek.

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]}" 

Bir boru zincirindeki tüm programların dönüş kodunu görmek için PIPESTATUS kullanma.

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ı $? 

Bir boru zincirinde hata içeren bir komut dosyası çalıştırma.

İ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ı $? 

Boru zincirlerindeki hataları yakalayan ve dönüş kodunu doğru şekilde ayarlayan bir komut dosyası çalıştırmak.

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ı $? 

Başlatılmamış değişkenleri yakalamayan bir komut dosyası çalıştırma.

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.

Bash'de Değişkenlerle Nasıl Çalışılır
İLGİLİ Bash'de Değişkenlerle Nasıl Çalışılır

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şkenleri yakalayan bir komut dosyası çalıştırma.

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 

Başlatılmamış değişkenlerin dahili olarak işlendiği ve -u seçeneğinin tetiklenmediği iki komut dosyası çalıştırma.

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 

Terminale yazılan -x izleme satırlarıyla bir komut dosyası çalıştırma.

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.