Linux Bash Script Yazım Teknikleri

Bu yazıda, temel Linux gezinme ve komut bilginizin olduğu farz edilmiştir. Temel bilgilerinizi birleştirerek Script yazmayı göreceğiz. Script yazma mevzusu gerçekte fazlaca detaylı olduğundan, burada genel olarak ele alınacaktır. Bash Script mevzusunda daha detaylı data için öteki kaynaklara da bakmanızı tavsiye ediyoruz.
Bu mevzuda anlatılanların bir kısmını ilk kez görüyorsanız kaygı etmeyin. Internet sitemizdeki ilgili öteki yazılara bakarak o mevzuları da kolaylıkla inceleyebilirsiniz.
Bash Script, bilgisayar terimleri açısından bakıldığında Bash Senaristliği anlamına gelmektedir. Bir başka ifade ile, Shell ortamında meydana gelebilecek ihtimallere gore senaryolar yazarak, mümkün olan tüm durumları karşılayan program geliştirmektir. Tiyatroda senaryo, oyuncular tarafınca sahnelenirken, burada bilgisayar tarafınca sahnelenmektedir. Bir A durumu meydana vardığında ekrana şunu yaz. Bir B durumu meydana vardığında dosyayı kopyala vb. işlemlerin hepsinin bir dosya içinde Script (Senaryo) olarak toplanmasına Bash Scripting denilmektedir.
Bash script yardımıyla, sık sık karşılaşılan durumlar için kullanıcı müdahalesine gerek kalmadan işlemlerin otomatikleştirilmesi sağlanabilir. Her gün belli zamanlarda sisteminizin tüm dosyalarının denetim edilerek içlerinden yalnız bundan önceki güne gore değişenlerin yedeğini alan bir program yazılabilir. Bu tür işlemleri her gün kullanıcı manuel olarak yapabileceği şeklinde bir programa da yaptırabilir.
Bu şekilde bir programı C, Python vb. Programlama dillerini kullanarak yazabilirsiniz. Bu durumda yazdığınız program, çalışmak için bir derleyiciye gereksinim duyacaktır. Bir script de aynı şekilde çalışmak için bir derleyiciye gereksinim duyar (bash shell). Biz örneklerimizde Bourne Again Shell (bash) kullanıyoruz.
Bir komut, shell içinde çalışıyorsa onu Script içine de yerleştirebilirsiniz.
Bir komut Script içine yerleştirilebiliyorsa, komut satırında da çalışıyor olmalıdır.
Burada anlatılan kuralı şöyleki uyguluyoruz. Script yazarken, parçaların çalışıp çalışmadığını komut satırında kontrol edebilirsiniz. Aldığınız kontrol sonucu doğruysa, Script içine ekleyebilirsiniz.
Bash Script, esasen düz metin satırlarından oluşan bir dosyadır. İstediğiniz bir metin editörü kullanarak yazabilirsiniz. Nano, vi yada emacs bunlardan bir kaçıdır.
Rahat Bir Örnek
Rahat bir örnek yardımıyla mevzuya giriş yapıyoruz. Aşağıda bulunan dosya içeriğini kopyalayıp bir editör yardımıyla myscript.sh olarak kaydedelim..
#!/bin/bash # Rahat bir Bash Script # Ümit 10/05/2016 echo İşte sizin Ev klasörünüzdeki dosyalar: ls ~
Kaydettiğimiz dosyanın hususi durumunu executable (x) olarak değiştirmemiz gerekmektedir. Komut satırından chmod +x myscript.sh komutunu kullanabilir, Görsel Arayüz (GUI) içinde ise dosya yöneticisinde dosyaya sağ tıklayıp çalıştırılabilir hale getirebilirsiniz.
chmod +x myscript.sh ls -l myscript.sh -rwxr-xr-x 1 ümit ümit 112 May 10 21:12 myscript.sh
Yukarıdaki komut ile yetki kontrolü yaptık. Şimdi de aşağıdaki komutla Script dosyamızı çalıştıralım. Burada dosyanın başına ./ yazıldığına dikkat edin. Bu mevzuyu aşağıda ayrı bir başlıkta açıkladık.
./myscript.sh ---ÇIKTI--- İşte sizin Ev klasöründeki dosyalar: Downloads Pictures Templates Dropbox kontrol.txt
Script Kodlarının Açıklaması:
#!/bin/bash # Rahat bir Bash Script # Ümit 10/05/2016 echo İşte sizin Ev klasörünüzdeki dosyalar: ls ~
.sh uzantısı
Linux, emek verme esnasında dosya uzantılarına gereksinim duymayan bir İşletim sistemidir. Dosya uzantıları, kullananların dosyaları daha süratli algılaması için kullanılırlar sadece mecburi değillerdir. myscript dosyamızın uzantısı .sh olmak zorunda olmadığı halde .sh ifadesi onun bir bash script dosyası bulunduğunu derhal anlamamıza destek olmaktadır.
#!/bin/bash
#!:Bir script dosyasının ilk satırı bu iki karakterle başlamalıdır. Shebang olarak anlatılan bu karakterlerden derhal sonrasında, boşluk bırakmadan hangi bash programı kullanılacaksa o programın mutlak adresi yazılır.
/bin/bash: Burada belirtilmesi ihtiyaç duyulan öteki bir mevzu da sisteminizde hangi bash yazılımını kullandığınızdır. which bash komutunun sonucu size mutlak adresi söyleyecektir. #! ifadesinden sonrasında herhangi bir bash adresi yazmasanız da Script çalışabilir. Fakat sizin yazdığınız Script başka bir sistemde çalıştırılmak istendiğinde hata verme ihtimali vardır. Bu sebeple bash adresini yazmayı alışkanlık haline getirmek daha sıhhatli olacaktır.
# Rahat bir Bash Script
# ifadesiyle başlamış olan satırlar yorum satırlarıdır. Bu satırları Bash yorum olarak farz edecek ve işleme almayacaktır. Dosyanın sahibi, oluşturulma zamanı ve oluşturulma maksadı vb. bilgilere burada yer verebilirsiniz.
Kodlarınız ve satırlar çoğaldıkça, hangi kodların ne işe yaradığını yeniden anımsamak zorlaşacaktır. Bununla beraber kodlarınızı bir başkasının incelemesi gerektiğinde, yorum bölümleri oldukça ehemmiyet kazanır. Kodlarınızın yanına kısa yorumlar ve açıklamalar eklemeyi alışkanlık haline getirmek oldukça önemlidir. Her satıra gerek olmasa da kodlarınızın mühim bölümlerine yorum ve açıklamalar yazmanızı tavsiye ediyoruz.
echo İşte sizin Ev klasörünüzdeki dosyalar
Burada, echo komutu ile bir mesajı ekrana yazdırıyoruz. Bu örnekte durağan(durgun) bir metin kullandık sadece ilerleyen bölümlerde değişkenlerin ve öteki değerlerin ekrana yazdırılması için sık sık echo komutunu kullanacağız.
ls ~
Son satırımızda ls komutu ile Ev klasörünün listesini ekrana yazdırıyoruz.
Yukarıdaki örnek Script teriminin açıklanması için oluşturulmuştur. Görünürde yalnız iki satır komutu çalıştırmak şeklinde kolay bir işlevi yerine getirmiş olabilir. Script dosyalarının içinde ne olduğu geliştirildikçe, fazlaca daha karışık işlemleri iyi mi basitleştirdiklerini aşağıda göreceğiz.
Niçin ./ ?
Linux komut satırına bir program yazdığınızda, sisteminiz o programı PATH adında olan değişkende tutulan klasörlerde arayacaktır. Sizin oluşturduğunuz myscript.sh dosyası, muhtemelen bu klasörlerin içinde bir yerde değildir zira Linux güvenlik açısından kullanıcının erişebileceği klasör yetkilerini sınırlar.
Linux sisteminizin, yazdığınız komutu hangi klasörlerde aradığını echo $PATH komutu ile öğrenebilirsiniz. myscript.sh dosyanız bu klasörlerde değil başka bir yerde kayıtlıdır. Bu durumda Linux’a PATH klasörlerinde arama, şu an bulunduğum klasördeki myscript.sh programını çalıştır diye belirtmeniz gereklidir. İşte şu an bulunduğum klasör ifadesi ./ işaretiyle gerçekleştirilir.
İsterseniz PATH değişkenine klasör ilave edebilirsiniz sadece bu güvenlik açısından daima iyi olmayabilir. Yazdığınız Script içinde bağıl adresleme (./) kullanarak kod yazmak, başka kullananların da bu scripti kullanabilmesine olanak verir.
Değişkenler
Değişkenler hafızalarında değerler tutan, referans olarak kullanılan ve gerektiğinde değişebilen kullanımlardır. Hafızada bir miktar yer ayırıp içinde bir kıymet tutarsınız ve ihtiyacınız olduğunda başka bir bellek alanı kullanmadan değişkenin kıymetini değiştirip yeniden kullanabilirsiniz. Fazlaca kullanışlı bir yapı olan değişkenlerin kullanımında uyulması ihtiyaç duyulan bazı kurallar bulunmaktadır. Bu kurallara kesinlikle uymalısınız.
- Bir değişken tanılarken onun ADINI yazarız ve asla boşluk bırakmadan eşittir (=) işaretiyle devam ederiz. Eşittir işaretinden sonrasında da boşluk bırakmadan TEK DÜZ TIRNAK içinde kıymeti yazarız. Not: Tırnaklar içine bir kıymet değil de bir komut sonucu da yazdırılabilir sadece onu birazdan göreceğiz.
- Bir değişkene atıfta bulunup referans göstermek istediğinizde, değişken isminin başına ( $ ) işareti konulmalıdır.
Örnek:
Ilk olarak degiskenornek.sh adlı bir dosya oluşturalım.
nano degiskenornek.sh
Oluşturulan dosyaya, aşağıdaki kodları yapıştırın. Bazı sistemlerde yapıştırma Shift+Ctrl+v ile yapılır. Yapıştırma işleminden sonrasında Ctrl+x ile çıkış isteği yapalım ve kaydetmek istiyor musunuz? sorusuna EVET cevabı verelim.
#!/bin/bash # Rahat bir değişken örneği # Ümit 11/05/2016 name='Ümit' echo Merhaba $name
Aşağıdaki komut yardımıyla dosyayı çalıştırılabilir yaptık ve çalıştırdık.
chmod +x degiskenornek.sh ./degiskenornek.sh ---ÇIKTI--- Merhaba Ümit
Izahat:
name='Ümit'
name değişkenin adıdır. Atıfta bulunacağımız vakit $name olarak çağırmalıyız. Eşittir işaretinin sağ ve solunda boşluk olmadığına dikkat edin. TEK DÜZ TIRNAK içine de değerimiz (Ümit) yazılmıştır.
echo Merhaba $name
Burada ise echo komutundan Merhaba durağan(durgun) kıymeti ile $name değişken kıymetini alarak ekrana yazdırması açıklanmıştır.
ALIŞTIRMA: degiskenornek.sh dosyasını yeniden açıp içine surname değişkenini ve kıymetini tanımlayın. Echo komutunu
echo Merhaba $name $surname
olarak değiştirip kaydedin ve çıkın. Yazdığınız scripti yeniden çalıştırın.
Script Çalıştırdığınızda Arka Plandaki Değişkenler
Siz bir Script yazıp çalıştırdığınızda, sizin tanımladığınız değişkenlere ilave olarak sisteminiz de otomatikman bir ekip değişkenleri hayata geçirir. Bunlardan bazılarını aşağıda açıkladık:
- $0 – Scriptin adı bu değişkende tutulur.
- $1 – $9 – Scripte komut satırından (dışarıdan gönderilen) argümanlar 1 ile 9 arasındaki değişkenlerde kayıt edilir.
- $# – Scripte dışarıdan gönderilen toplam argüman sayısı bu değişkende tutulur.
- $* – Scripte dışarıdan gönderilen argümanların tamamı anlamına gelir.
Örnek:
Yukarıdaki örnekte yaptığımıza benzer şekilde aşağıdaki nano komutuyla bir dosya oluşturalım.
nano otomatikornek.sh
Oluşturulan dosyaya, aşağıdaki Script kodlarını yapıştıralım.
#!/bin/bash # Basitin birazcık ötesinde değişken örneği # Ümit 11/05/2016 clear echo Ben: Benim adım $0 ve ben komut satırından toplam $# argüman gönderdim. echo Bilgisayar: Evet, gönderdikleriniz bunlardı: $* echo Bilgisayar: Ve gönderdiğiniz 2. argüman da $2, doğru mu? :)
Dosyayı çalıştırılabilir yapalım ve çalıştıralım.
chmod +x otomatikornek.sh ./otomatikornek.sh Ümit Serhat Mesut ---ÇIKTI--- Benim adım ./otomatikornek.sh ve ben komut satırından toplam 3 argüman gönderdim. Bilgisayar: Evet, gönderdikleriniz bunlardı: Ümit Serhat Mesut Bilgisayar: Ve gönderdiğiniz 2. argüman da Serhat , doğru mu? :)
Izahat:
echo Ben: Benim adım $0 ve ben komut satırından toplam $# argüman gönderdim.
Bu satırda $0 ile script dosyasının adı çağrılmış ve $# ile toplam argüman sayısı kullanılmıştır.
echo Bilgisayar: Evet, gönderdikleriniz bunlardı: $*
Bu satırda $* ile değişkenlerin tamamı yazdırılmıştır.
echo Bilgisayar: Ve gönderdiğiniz 2. argüman da $2, doğru mu? :)
Bu satırda $2 ile gönderilen 2.sıradaki argüman değişkeni çağrılmış ve ekrana yazdırılmıştır.
ALIŞTIRMA:
Scripte 1 argüman gönderseydik ne olurdu?
Scriptte 🙂 yazdığımız halde çıktıda niçin : ) olarak görünüyor?
Ters Tırnaklar
Yukarıdaki örneklerde değişkenlerimizi TEK DÜZ TIRNAK içinde durağan(durgun) string değerler olarak tanımladık. Kimi zaman bir değişkene, bir komutun sonucunu kaydetmek isteyebiliriz. Bu durumda durağan(durgun) değil bir komutu tanımlamamız gerekecektir. Bu şekilde durumlarda değişkenin eşittir işaretinin sağ tarafında bulunan ifadeyi TERS TIRNAK (`ifade`) içinde yazmamız gerekecektir. Klavyelerimizde yeri pek bilinmeyen bu işaret çoğu zaman , ve ; tuşunda (TR Q) bulunur. AltGr tuşuyla beraber virgül karakterinin bulunmuş olduğu tuşa basarak yazabilirsiniz. Bununla ilgili bir örnek yapalım.
Örnek:
Bu komut ile terstirnak.sh dosyasını nano editörde oluşturalım.
nano terstirnak.sh
Aşağıdaki script kodlarını terstirnak.sh dosyası içine yapıştıralım ve Ctrl+x ile çıkış isteği yapalım.
#!/bin/bash # Rahat bir TERS TIRNAK içinde değişken örneği # Ümit 11/05/2016 sistem=`uname -a` echo Sistem bilginiz: $sistem
terstirnak.sh dosyasını çalışır hale getirelim ve çalıştıralım.
chmod +x terstirnak.sh ./terstirnak.sh ---ÇIKTI--- Sistem bilginiz: Linux umut-X550JX 4.4.0-21-generic #37~14.04.1-Ubuntu SMP Wed Apr 20 16:33:38 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
Izahat:
sistem=`uname -a`
uname -a bir komuttur. Echo ekrana Ters Tırnaklar içindeki ifadeyi aynen değil, komutun sonucunu yazdırmıştır.
ALIŞTIRMA:
Script dosyasındaki sistem değişkenine başka komutlar yazarak neticeleri gözlemleyin.
Rahat Bir Yedekleme Script Dosyası
Aşağıda, adını verdiğiniz bir klasörü, yedeklerinizin bulunmuş olduğu bir öteki klasöre yedekleme meydana getiren Script verilmiştir. İsterseniz ayrı bir .sh dosyası oluşturarak deneyebilirsiniz. İsterseniz de kodlar üstünden hangi işlemlerin yapıldığını takip edebilirsiniz. Şu ana kadar anlatılanların pekişmesi açısından üstünde çalışmanızı tavsiye ediyoruz.
Script, Sisteminize bir zarar meydana getirmemesi için oluşturacağı klasör ve dosyaları /tmp klasörüne kaydedecektir.
nano backup.sh
#!/bin/bash # Bir yedekleme örneği # Ümit 11/05/2016 clear date=`date +%F` mkdir /tmp/$1&&touch /tmp/$1/dosya1.txt /tmp/$1/dosya2.txt echo /tmp Klasörüne $1 Klasörü ve içinde ne olduğu oluşturuldu. sleep 5 mkdir -p /tmp/backups/$1_$date echo /tmp Klasörüne /backup klasörü ve $1_$date Klasörü oluşturuldu. sleep 5 cp -R /tmp/$1 /tmp/backups/$1_$date echo /tmp klasöründe bulunan $1 klasör içinde ne olduğu /tmp/backups/$1_$date klasörüne yedeklendi. sleep 5 echo Yedekleme tamamlandı. echo isterseniz /tmp/$1 klasörünü ve echo /tmp/backups/$1_$date klasörünü silebilirsiniz. echo /tmp klasörü sisteminizi kapattığınızda kendisi esasen silinir. sleep 1 echo ESAS KLASÖR İÇERİĞİ ls -l /tmp/$1 sleep 1 echo YEDEKLENEN KLASÖR İÇERİĞİ ls -l /tmp/backups/$1_$date/$1/ echo Script sonlandı…
chmod +x backup.sh ./backup.sh yedekleme
If -Then-Else Kullanımı
Yukarıdaki yedekleme örneğinde işlemlerin hatasız yapıldığı farz edilmiştir. Meydana getirilen işlemlerin herhangi bir adımında problem çıkması durumda ne yapılacağı senaryoda yoktur. Bu tür durumlar için Script yazarken kullanılan koşul ve durumsal yapılardan bir tanesi If yapısıdır.
If yapısı, bir şartı denetim eder ve o koşul sağlanıyorsa işlemi yapar. Sağlanmıyorsa işlemi iptal eder. Bir nevi ön denetim yapar. Denetim, işlem gerçekleşmeden ilkin yapılmaktadır.
Aşağıdaki örneği, önceki örneklerde olduğu şeklinde bir .sh dosyası oluşturup kaydedebilir yada kodlar üstünden de inceleyerek anlamaya çalışabilirsiniz.
#!/bin/bash # Bir yedekleme örneği # Ümit 11/05/2016 if [ $# != 1 ] then clear echo Kullanım: Yedeklenecek klasörü belirten 1 tek klasör adı girmelisiniz. exit fi if [ ! -d /tmp/$1 ] then clear echo 'Adını verdiğiniz klasör bulunmuyor. Yeni klasör ve içinde ne olduğu oluşturulacak' mkdir /tmp/$1&&touch /tmp/$1/dosya1.txt /tmp/$1/dosya2.txt echo /tmp Klasörüne $1 Klasörü ve içinde ne olduğu oluşturuldu. sleep 5 fi echo --------------------------- date=`date +%F` # Bugün yedeği alınmış başka bir klasör var mı diye bakıyoruz? if [ -d /tmp/backups/$1_$date ] then echo 'Bu klasörün bugün yedeği alınmış. Gene de üzerine yazılsın mı?' read answer if [ $answer != 'y' ] then exit fi else mkdir -p /tmp/backups/$1_$date echo /tmp Klasörüne /backup klasörü ve $1_$date Klasörü oluşturuldu. sleep 5 fi cp -R /tmp/$1 /tmp/backups/$1_$date echo /tmp klasöründe bulunan $1 klasör içinde ne olduğu /tmp/backups/$1_$date klasörüne yedeklendi. sleep 5 echo Yedekleme tamamlandı. echo isterseniz /tmp/$1 klasörünü ve echo /tmp/backups/$1_$date klasörünü silebilirsiniz. echo /tmp klasörü sisteminizi kapattığınızda kendisi esasen silinir. sleep 1 echo ESAS KLASÖR İÇERİĞİ ls -l /tmp/$1 sleep 1 echo YEDEKLENEN KLASÖR İÇERİĞİ ls -l /tmp/backups/$1_$date/$1/ echo Script sonlandı…
Izahat:
1.Kullanım:
if koşul=eşleşiyor then işlemleri yap exit fi
Yukarıdaki örnekte ilk if kullanımı [ $# != 1 ] şartı ile denetim yapmaktadır. Bu koşul, Scripte dışarıdan girilen argüman sayısının bire eşit olmaması durumudur. Öyleyse burada Script’e girilen argüman bire eşit değilse kısaca (0 yada Birden fazla argüman girildiyse) bir ekip işlemleri yapmış olup çıkması istenmiştir.
2.Kullanım:
if şart1=eşleşiyor then işlemleri yap if şart2=eşleşiyor then işlemleri yap exit fi else şart1 gerçekleşmediğinde bu işlemleri yap exit fi:
Yukarıdaki örnek içinde 2.kullanım şekli de if yapısını ELSE kısaca öteki türlü olduğunda yapılacak işlemleri de tanımlayarak algoritmayı genişleterek kullandık. Üstelik şart1 gerçekleştiğinde yapılacak işlemler arasına da bir if kullanımı yerleştirerek içiçe kullanımı da göstermiş olduk. Bu biçim kullanımda if denetim mekanizmasına [-d /tmp/backups/$1_$date ] şartı ile yedeğin bugün içinde evvel alınıp alınmadığı denetim ettiriliyor. Alınmışsa takip edilecek yol ve işlemler belirtiliyor. Alınmamış ise (ELSE) yapılacak işlemler belirtiliyor.
3.Kullanım:
echo 'Bu klasörün bugün yedeği alınmış. Gene de üzerine yazılsın mı?' read answer if [ $answer != 'y' ] then exit
Burada ise, kullanıcıya bir sual soruluyor ve cevabı planlanıyor. Girilen yanıt read answer komutu ile answer değişkenine yerleştiriliyor, sonrasında if-then yapısıyla denetim ediliyor. Girilen yanıt y değilse [!=’y’] çıkılıyor.
ALIŞTIRMA: Kullanıcı yanıt olarak y tuşuna basması icap ettiğini nereden bilecek?