Çalıştırmadan Önce Bir Linux Bash Komut Dosyasının Sözdizimini Doğrulama
Yayınlanan: 2022-06-16Linux Bash komut dosyalarındaki hatalar ve yazım hataları, komut dosyası çalıştırıldığında korkunç şeyler yapabilir. Komut dosyalarınızı çalıştırmadan önce sözdizimini kontrol etmenin bazı yolları.
Bu Sinir bozucu Böcekler
Kod yazmak zordur. Veya daha doğrusu, hatasız, önemsiz olmayan kod yazmak zordur. Ve bir programda veya komut dosyasında ne kadar çok kod satırı varsa, içinde hata olma olasılığı o kadar artar.
Programladığınız dilin bunda doğrudan bir etkisi vardır. Montajda programlama, C'de programlamadan çok daha zordur ve C'de programlama, Python'da programlamadan daha zordur. Programladığınız dil ne kadar düşük seviyedeyse, kendiniz için o kadar çok iş yapmanız gerekir. Python, yerleşik çöp toplama rutinlerinden hoşlanabilir, ancak C ve derleme kesinlikle yapmaz.
Linux kabuk komut dosyaları yazmak, kendi zorluklarını ortaya çıkarır. C gibi derlenmiş bir dilde, derleyici adı verilen bir program, kaynak kodunuzu (bir metin dosyasına yazdığınız insan tarafından okunabilen yönergeleri) okur ve onu bir ikili yürütülebilir dosyaya dönüştürür. İkili dosya, bilgisayarın anlayabileceği ve buna göre hareket edebileceği makine kodu talimatlarını içerir.
Derleyici, yalnızca okuduğu ve ayrıştırdığı kaynak kod sözdizimine ve dilin diğer kurallarına uyuyorsa bir ikili dosya oluşturur. Dilin komut sözcüklerinden biri olan ayrılmış bir sözcüğü veya bir değişken adını yanlış yazarsanız, derleyici hata verir.
Örneğin, bazı diller, kullanmadan önce bir değişken tanımlamanız konusunda ısrar ederken, diğerleri o kadar telaşlı değildir. Çalıştığınız dil değişkenleri bildirmenizi gerektiriyorsa ancak bunu yapmayı unutursanız, derleyici farklı bir hata mesajı verecektir. Bu derleme zamanı hataları ne kadar can sıkıcı olsa da, birçok sorunu yakalar ve sizi bunları çözmeye zorlar. Ancak, sözdizimsel hataları olmayan bir programınız olsa bile, bu, içinde hiç hata olmadığı anlamına gelmez. Ne münasebet.
Mantıksal kusurlardan kaynaklanan hataları tespit etmek genellikle çok daha zordur. Programınıza iki ve üç toplamasını söylerseniz, ancak gerçekten iki ile ikiyi toplamasını istiyorsanız, beklediğiniz cevabı alamazsınız. Ama program ne yazdıysa onu yapıyor. Programın oluşumunda veya sözdiziminde yanlış bir şey yok. Sorun sensin. İstediğinizi yapmayan iyi biçimlendirilmiş bir program yazdınız.
Test Zordur
Basit bir program bile olsa bir programı baştan sona test etmek zaman alıcıdır. Birkaç kez çalıştırmak yeterli değildir; kodun tüm bölümlerinin doğrulanması için kodunuzdaki tüm yürütme yollarını gerçekten test etmeniz gerekir. Program girdi isterse, kabul edilemez girdiler de dahil olmak üzere tüm koşulları test etmek için yeterli bir dizi girdi değeri sağlamanız gerekir.
Daha yüksek seviyeli diller için birim testleri ve otomatik testler, kapsamlı testlerin yönetilebilir bir alıştırma olmasına yardımcı olur. Soru şu ki, hatasız Bash kabuk komut dosyaları yazmamıza yardımcı olacak herhangi bir araç var mı?
Cevap, Bash kabuğunun kendisi de dahil olmak üzere evet.
Komut Dosyası Sözdizimini Kontrol Etmek İçin Bash Kullanma
Bash -n
(noexec) seçeneği, Bash'e komut dosyasını çalıştırmadan bir komut dosyasını okumasını ve sözdizimsel hataları kontrol etmesini söyler. Komut dosyanızın ne amaçladığına bağlı olarak, bu, onu çalıştırmaktan ve sorun aramaktan çok daha güvenli olabilir.
İşte kontrol edeceğimiz senaryo. Karmaşık değildir, esas olarak bir if
ifadeleri kümesidir. Bir ayı temsil eden bir sayı ister ve kabul eder. Senaryo, ayın hangi mevsime ait olduğuna karar verir. Açıkçası, kullanıcı hiç girdi sağlamazsa veya rakam yerine harf gibi geçersiz girdi sağlarsa bu işe yaramaz.
#! /bin/bash read -p "Bir ay girin (1 ila 12): " ay # bir şey girdiler mi? eğer [ -z "$ay" ] sonra echo "Bir ayı temsil eden bir sayı girmelisiniz." çıkış 1 fi # geçerli bir ay mı? if (( "$ay" < 1 || "$ay" > 12); sonra echo "Ay 1 ile 12 arasında bir sayı olmalıdır." 0 çıkışı fi #bahar ayı mı? if (( "$ay" >= 3 && "$ay" < 6); sonra echo "Bu bir Bahar ayı." 0 çıkışı fi # Yaz ayı mı? if (( "$ay" >= 6 && "$ay" < 9); sonra echo "Bu bir Yaz ayı." 0 çıkışı fi # Sonbahar ayı mı? if (( "$ay" >= 9 && "$ay" < 12); sonra echo "Bu bir Sonbahar ayı." 0 çıkışı fi # kış ayı olmalı echo "Bu bir Kış ayı." 0 çıkışı
Bu bölüm, kullanıcının herhangi bir şey girip girmediğini kontrol eder. $month
değişkeninin ayarlanmamış olup olmadığını test eder.
eğer [ -z "$ay" ] sonra echo "Bir ayı temsil eden bir sayı girmelisiniz." çıkış 1 fi
Bu bölüm, 1 ile 12 arasında bir sayı girip girmediklerini kontrol eder. Harfler ve noktalama işaretleri sayısal değerlere dönüşmediğinden, rakam olmayan geçersiz girişi de yakalar.
# geçerli bir ay mı? if (( "$ay" < 1 || "$ay" > 12); sonra echo "Ay 1 ile 12 arasında bir sayı olmalıdır." 0 çıkışı fi
Diğer tüm If yan tümceleri, $month
değişkenindeki değerin iki değer arasında olup olmadığını kontrol eder. Eğer öyleyse, ay o mevsime aittir. Örneğin, kullanıcı tarafından girilen ay 6, 7 veya 8 ise Yaz ayıdır.
# Yaz ayı mı? if (( "$ay" >= 6 && "$ay" < 9); sonra echo "Bu bir Yaz ayı." 0 çıkışı fi
Örneklerimiz üzerinde çalışmak istiyorsanız, komut dosyasının metnini kopyalayıp bir düzenleyiciye yapıştırın ve "seasons.sh" olarak kaydedin. Ardından, chmod
komutunu kullanarak komut dosyasını yürütülebilir hale getirin:
chmod +x mevsimler.sh
Senaryoyu şu şekilde test edebiliriz:
- Hiçbir girdi sağlama.
- Sayısal olmayan bir giriş sağlama.
- 1 ila 12 aralığının dışında bir sayısal değer sağlama.
- 1 ila 12 aralığında sayısal değerler sağlamak.
Her durumda, betiği aynı komutla başlatırız. Tek fark, kullanıcının komut dosyası tarafından tanıtıldığında sağladığı girdidir.
./sezonlar.sh
Bu beklendiği gibi çalışıyor gibi görünüyor. Bash'e betiğimizin sözdizimini kontrol ettirelim. Bunu -n
(noexec) seçeneğini çağırarak ve betiğimizin adını ileterek yaparız.
bash -n ./sezonlar.sh
Bu, “hiç haber iyi haber değildir” olgusudur. Bizi sessizce komut istemine döndürmek, Bash'in her şeyin yolunda olduğunu söyleme şeklidir. Senaryomuzu sabote edelim ve bir hata sunalım.
İlk if
tümcesinden then
zaman öğesini kaldıracağız.
# geçerli bir ay mı? if (( "$ay" < 1 || "$ay" > 12); # "sonra" kaldırıldı echo "Ay 1 ile 12 arasında bir sayı olmalıdır." 0 çıkışı fi
Şimdi betiği önce kullanıcı girdisi olmadan sonra da kullanıcı girdisi ile çalıştıralım.
./sezonlar.sh
Komut dosyası ilk çalıştırıldığında kullanıcı bir değer girmez ve bu nedenle komut dosyası sonlandırılır. Sabote ettiğimiz bölüme bir türlü ulaşılamıyor. Betik, Bash'den bir hata mesajı olmadan sona erer.
Komut dosyası ikinci kez çalıştırıldığında, kullanıcı bir girdi değeri sağlar ve ilk if cümlesi, kullanıcının girdisini akıl sağlığı açısından kontrol etmek için yürütülür. Bu, Bash'ten gelen hata mesajını tetikler.
Bash'in bu yan tümcenin sözdizimini - ve diğer tüm kod satırlarını - kontrol ettiğini unutmayın, çünkü komut dosyasının mantığını umursamaz. Bash komut dosyasını kontrol ettiğinde komut dosyası çalışmadığından kullanıcıdan bir sayı girmesi istenmez.
Komut dosyasının farklı olası yürütme yolları, Bash'in sözdizimini nasıl kontrol ettiğini etkilemez. Bash, her satırın sözdizimini kontrol ederek, komut dosyasının tepesinden altına kadar basit ve metodik bir şekilde çalışır.
ShellCheck Yardımcı Programı
Unix'in en parlak döneminden bir C kaynak kodu kontrol aracı olarak adlandırılan bir linter, programlama hatalarını, biçimsel hataları ve dilin şüpheli veya şüpheli kullanımını tespit etmek için kullanılan bir kod analiz aracıdır. Linterler birçok programlama dili için mevcuttur ve bilgiçlikleriyle tanınırlar. Bir linter'in bulduğu her şey başlı başına bir hata değildir, ancak dikkatinizi çekecek her şey muhtemelen dikkati hak eder.
ShellCheck, kabuk komut dosyaları için bir kod analiz aracıdır. Bash için bir linter gibi davranır.
Eksik ve then
ayrılmış kelimemizi komut dosyamıza geri koyalım ve başka bir şey deneyelim. İlk if
cümlesinden “[” açılış parantezini kaldıracağız.
# bir şey girdiler mi? if -z "$ay" ] # açılış parantez "[" kaldırıldı sonra echo "Bir ayı temsil eden bir sayı girmelisiniz." çıkış 1 fi
betiği kontrol etmek için Bash kullanırsak bir sorun bulmaz.
bash -n mevsimler.sh
./sezonlar.sh
Ancak betiği çalıştırmayı denediğimizde bir hata mesajı görüyoruz. Ve hata mesajına rağmen komut dosyası çalışmaya devam ediyor. Bu yüzden bazı böcekler çok tehlikelidir. Komut dosyasında daha sonra gerçekleştirilen eylemler, kullanıcıdan gelen geçerli girdilere dayanıyorsa, komut dosyasının davranışı tahmin edilemez olacaktır. Verileri potansiyel olarak riske atabilir.
Bash -n
(noexec) seçeneğinin komut dosyasındaki hatayı bulamamasının nedeni, “[” açılış parantezinin [
adlı harici bir program olmasıdır. Bash'in bir parçası değil. test
komutunu kullanmanın kısa bir yoludur.
Bash, bir betiği doğrularken harici programların kullanımını kontrol etmez.
ShellCheck'i Yükleme
ShellCheck kurulum gerektirir. Ubuntu'ya yüklemek için şunu yazın:
sudo apt shellcheck'i kurun
ShellCheck'i Fedora'ya kurmak için bu komutu kullanın. Paket adının karışık durumda olduğunu unutmayın, ancak komutu terminal penceresinde verdiğinizde tümü küçük harflidir.
sudo dnf ShellCheck'i kurun
Manjaro ve benzeri Arch tabanlı dağıtımlarda pacman
kullanıyoruz:
sudo pacman -S kabuk denetimi
ShellCheck'i kullanma
Komut dosyamızda ShellCheck'i çalıştırmayı deneyelim.
shellcheck mevsimler.sh
ShellCheck sorunu bulur ve bize bildirir ve daha fazla bilgi için bir dizi bağlantı sağlar. Bir bağlantıya sağ tıklayıp açılan içerik menüsünden "Bağlantıyı Aç"ı seçerseniz bağlantı tarayıcınızda açılır.
ShellCheck ayrıca, o kadar ciddi olmayan başka bir sorun bulur. Yeşil metinle bildirilir. Bu, bunun bir uyarı olduğunu, bir hata olmadığını gösterir.
Hatamızı düzeltelim ve eksik olan “[”yi değiştirelim. Bir hata düzeltme stratejisi, önce en yüksek öncelikli sorunları düzeltmek ve daha sonra uyarılar gibi daha düşük öncelikli sorunlara kadar çalışmaktır.
Eksik “[”yi değiştirdik ve ShellCheck'i bir kez daha çalıştırdık.
shellcheck mevsimler.sh
ShellCheck'in tek çıktısı önceki uyarımıza atıfta bulunuyor, yani bu iyi. Düzeltilmesi gereken yüksek öncelikli sorunlarımız yok.
Uyarı bize -r
(olduğu gibi oku) seçeneği olmadan read
komutunun kullanılmasının girişteki ters eğik çizgilerin kaçış karakterleri olarak değerlendirilmesine neden olacağını söyler. Bu, bir linter'in üretebileceği bilgiçlik çıktısının türüne iyi bir örnektir. Bizim durumumuzda, kullanıcı yine de ters eğik çizgi girmemelidir - bir sayı girmeleri gerekir.
Bunun gibi uyarılar, programcının bir karar vermesini gerektirir. Düzeltmek için çaba sarf etmek mi yoksa olduğu gibi bırakmak mı? İki saniyelik basit bir düzeltme. Ve ShellCheck'in çıktısını karıştıran uyarıyı durduracak, bu yüzden tavsiyesini alsak iyi olur. read
komutundaki bayrakları seçmek için bir “r” ekleyeceğiz ve betiği kaydedeceğiz.
read -pr "Bir ay girin (1 ila 12): " ay
ShellCheck'i bir kez daha çalıştırmak bize temiz bir sağlık raporu verir.
ShellCheck Arkadaşınızdır
ShellCheck, bir dizi sorunu tespit edebilir, raporlayabilir ve tavsiyelerde bulunabilir. Kaç tür sorunu algılayabileceğini gösteren hatalı kod galerisine göz atın.
Ücretsizdir, hızlıdır ve kabuk komut dosyaları yazmaktan çok fazla acı çeker. Sevilmeyecek ne var?