Shell(Bash,sh, zsh,) Programming- Kabuk Programlama

Shell(Bash,sh, zsh,) Programming- Kabuk Programlama – dostaki bat dosyasi benzer biçimde çalışabilir dosyalar oluşturma
Shell(Bash,sh, zsh,) Programming- Kabuk Programlama
Linux altında süratli ve ergonomik programlama yapmanın en kısa yolu shell(kabuk) programlamadır diyebiliriz. İşletim sisteminin naturel komutlarını çalıştırma ve ek herhangi bir yorumlayıcı istememesi shell script(betik) dilini ötekilerden ayıran en mühim faktördür. Yazdığınız bir kodu tüm Linux/UNIX sistemlerde değişim yapmadan kullanabilirsiniz. Linux altında shell(kabuk) programlama birçok değişik shell ile yapılabilir.
Linux ve UNIX sistemlerde yaygın kullanılan bazı kabuk(shell)lar;
sh (Shell , Bourne Shell): Ilk UNIX kabuğudur ve bir çok UNIX dağıtımı ile beraber öntanımlı kabuk olarak dağıtılır.
ksh (Korn Shell): sh uyumlu, birçok ek programlama özelliği de içeren bir kabuk.
bash(Bourne Again Shell): Kullanım kolaylığı bakımından en oldukça rağbet gören bash, sh ve ksh uyumluluğunu korurken, bilhassa etkileşimli kullanıma yönelik (komut tamamlama, benzer biçimde) birçok yenilik de ihtiva eder.
csh (C shell): Berkeley Üniversitesi’nde geliştirilen csh’in C diline benzer bir programlama yapısı vardır. Bilhassa programcılar tarafınca tercih edilir.
tcsh: csh’ın birazcık geliştirilmiş hali diyebiliriz.
Bash kullanarak ergonomik programlama
Linux üstünde kullanıcının işletim sistemini kullanımı için temel iki yol vardır. Bunlardan biri GUI olarak adlandırdığımız grafik arabirimler diğeri de konsol/shell olarak adlandırabileceğimiz komut satırı yönetimidir.
Kabuk programlamada aslına bakarsak konsoldan verilen komutları belirli bir düzene uyarak çalıştırmaktan ibarettir. Kısaca konsoldan çalıştırdığımız komutları bir dosyaya sırayla yazarak en basitinden bir shell script yazmış oluruz. Heralde belirli amaçlara yönelmiş programlar için fonksiyon, dizi , döngüler benzer biçimde daha üst düzey yapılar kullanmamız gerekebilir ki “bash” bu tarz şeyleri fazlasıyla sağlamaktadır.
Kod yazmaya başlamadan bir ek daha yapalım. Yazı süresince kodladığımız örnekleri sizlerde herhangi bir Linux altında yazıp çalıştırabilirsiniz. Editör olarak KDE altında Kedit, Gnome altında Gedit kullanmanızı tavsiye ederim. Eger her işimi konsoldan yapmak isterim derseniz pico, nano ya da Vi benzer biçimde konsol tabanlı editörleri de kullanmayı deneyebilirsiniz.
Eğer elinizin altında halihazırda bir Linux/UNIX yoksa ve kuracak durumda da değilseniz web üstünden ücretsiz bir şekilde Shell hesabı elde eden firmalardan bir hesap edinerek örnek kodları deneyebilirsiniz. http://www.ductape.net/~mitja/freeunix.shtml adresi çeşitli Linux ve UNIX sistemler üstünde ücretsiz bir şekilde shell hesabına haiz olmak isteyenler için iyi bir başlangıç noktası. Buradan bir hesap edindikten sonrasında Putty SSH programı ile sunucunuza bağlanarak örnek kodları çalıştırabilirsiniz.
Sözü fazla uzatmadan programlama dünyasının o meşhur ilk programı ile kodlamaya başlamış olalım.. Evet, “Hello World!
“ / “Merhaba dünya!” programından bahsediyorum.
#!/bin/bash
echo “Merhaba Dunya!”
Böylece ilk shell script(betik)imizi yazmış olduk. Yukarıdaki rahat programda dikkatimizi çeken bir satır var #!/bin/bash, bu satır sonraki alt satırların hangi kabuk tarafınca yorumlanacağını bildiren standart bir tanımdır ve her bash scriptinde olmalıdır. Eğer bash programı /bin/bash değilde değişik bir yerde ise scriptlerin başına o kıymet yazılmalıdır. Linux altında bir programın hangi dizin altında bulunduğunu which komutu ile bulabiliriz.
$ which bash
/bin/bash
Scriptimizi kaydettikten sonrasında çalıştırma hakkı verelim. Bunun için Linux dünyasında chmod komutu kullanılır. Scriptimizi hello.sh adı ile kaydettiğimizi varsayarsak aşağıdaki komut ile scriptimize çalıştırma hakkı vermiş oluruz.
$ chmod 700 hello.sh
$./hello.sh
Merhaba Dunya!
Çevresel Değişkenler
Her işletim sistemi çeşitli amaçlarla kullanılmak suretiyle çevresel değişkenlere haizdir. Linux benzer biçimde sistem yönetiminin çoğunlukla komut satırından yapıldığı sistemlerde bu değişkenlerin önemi bir kat daha fazladır.
Linux altında sık kullanılan çevresel değişkenler ve manaları:
HOME = O anki kullanıcının ev dizinini gösterir
USER = O anki kullanıcının kim bulunduğunu gösterir
PS1 = Kullanıcının komut satırındaki işaret( huzeyfe@ linux $ benzer biçimde)
SHELL = Kullanıcının komut yürttüğü kabuk adı
Çevresel değişkenleri aynı düzgüsel değişkenler benzer biçimde kullanabiliriz.
#echo $HOME
/root
$echo $SHELL
/bin/bash
Çevresel Değişken tanımlama
Çevresel değişkenler işletim sistemi kurulumu ile beraber hazır geleceği benzer biçimde kendimizde tanımlayabiliriz ve sürekli kullanım için kaydedebiliriz.
Örnek olarak YASAK_BOLGE diye bir çevresel değişken tanımlayıp bunu tüm programlar için geçerli kılmak istersek aşağıdaki komut işimizi görecektir.
$export YASAK_BOLGE=”/home/huzeyfe/tools/security”
Bu yaptığımız tanımlamalar sistemin bir sonraki açılışında kaybolacaktır, kalıcı hale getirmek için /etc/bashrc ya da kendi ev dizinimizdeki .bashrc dosyasına yazmalıyız.
Değişkenler
Programlama dillerinin olmazsa olmaz öğelerinden biri değişkenlerdir. Bash ile beraber değişken tanımı ve kullanımı oldukça kolaydır. Öteki dillerden değişik olarak tanımladığımız değişkenin tipinin belirtilmesine gerek kalmamıştır, değişkenin kullanıldığı yere bakılırsa tipi belirlenir.
$ adim= ‘Huzeyfe ONAL’
$echo $adim
Huzeyfe ONAL
Aynı değişkeni $adim=”Huzeyfe ONAL” seklinde de yapabilirdik. Değişken kullanırken çift tırnak (“ ”) ya da tek tırnak(‘ ’) kullanmanın farkı : “ ” içinde kullanacağımız bazı hususi karekterler BASH tarafınca değişik komutmuş benzer biçimde işlem görecektir . Örnek olarak bash için ! karekterinin hususi bir anlamı vardır ve biz bu karekteri “ “ içinde kullanırsak ekrana ! karekteri basılmazda ! karekterinin bash için ifade etmiş olduğu kıymet basılır. Bu tip hatalardan kaçınmak için yeri vardığında tek tırnak (‘ ‘) kullanılır. Çift tırnağın aksine tek tırnak içinde almış olduğu tüm karekterleri olduğu benzer biçimde yansıtır.
Komut çıktısını değişkene atama
Linux altında herhangi bir komutun çıktısı sonradan kullanmak amacıyla değişkene atılabilir. Çalıştırılan komutu () arasına alarak ve başına $ işareti koyarak değişkene atama yapar ve istediğimiz yerde kullanabiliriz, ne şekilde mi?
Örnek;
MYFILES=$(ls /etc | grep ab)
$ echo $MYFILES
crontab entropychatdisable fstab inittab mtab quotatab updfstab
İlk satırda /etc dizini listelenerek içinde ab kelimesi(birleşik ab karekterleri) geçen tüm dosyalar MYFILES değişkenine atanıyor. Sonraki satırda ise bu değişkenin içinde ne olduğu ekrana basılıyor. İlk satırdaki “| “ karekteri Linux dünyasında pipe olarak geçer ve bir komutun çıktısını bir sonraki komuta girdi olarak aktarmaya yarar, şu demek oluyor ki ls /etc/nin çıktısı grep komutuna parametre olarak aktarılmış
Hususi Değişkenler.
Bash ile programlama yaparken kullanabileceğimiz bazı hususi değişkenler vardır. Bu tarz şeyleri kullanmak için tanımlamamız gerekmez. Örnek olarak bu değişkenlerden {IcerikVeri} çalışan programın adını verirken ilk parametreyi , 2. parametreyi ve $# değişkeni de toplam parametre sayısını gösterir.
#!/bin/bash
echo “program adı= {IcerikVeri}”
echo “ilk parametre= “
echo “ikinci parametre=n”
echo “Toplam parametre sayisi=$# “
$ ./kontrol.sh parametre_1 parametre_2
program adı=kontrol.sh
ilk parametre= parametre_1
ikinci parametre= parametre_2
Toplam parametre sayisi=3
Kullanıcı ile kontakt
Yazacağımız scriptlerde kimi zaman kullanıcı ile kontakt gerekir, bu durumda read komutunu kullanarak kullanıcıdan data alır ve bu bilgiyi bir değişkene atayarak kullanabiliriz.
Kolay bir etkileşim scripti;
#!/bin/sh
echo –n “Adinizi Giriniz: ”
read name
echo “Merhaba $name !”
Scriptimize ad.sh olarak adlandırıp çalıştıralım
$chmod 700 ad.sh
$./ad.sh
Adinizi Giriniz: Engin KUŞAK
Merhaba Engin KUŞAK!
Read komutuna –t parametresi vererek kullanıcının belirli bir süre içinde giriş yapmasını sağlayabiliriz. Eğer belirlene sürede kullanıcı herhangi bir şey girmezse bir sonraki adım işleme sokulur şu demek oluyor ki kullanıcı hakkını yitirmiş olur. Benzer şekilde kullanıcının girmiş olduğu verileri ekrana yazmak istemezsek –sözgelişi parola gibi- read komutunu –s parametresi ile denemeliyiz.
Örnek;
#!/bin/bash
echo -n “3 saniye icinde giris yapmalisiniz! > ”
if read -t 3 response; then
echo “Basarilar, 3 saniyeyi gecirmediniz”
else
echo “Birazcık daha hizli yazmalisiniz!”
fi
echo -n “Kullanici Adiniz:”
read -t 4 user
echo -n “Parolaniz :”
read -s parola
echo “$user kullanicisi ve $parola sifresi ile sisteme giris yaptiniz!”
$./a.sh
3 saniye icinde giris yapmalisiniz! > aa1133
Basarilar, 3 saniyeyi gecirmediniz
Kullanici Adiniz:engin
Parolaniz :
elifsu kullanicisi ve Deneme123 sifresi ile sisteme giris yaptiniz!
Aritmetik işlemler
Temel 4 işlemi kullanarak bash altında ileri düzey matematik işlemleri yapabiliriz. Bash altında aritmetik işlemler için $(()) yapısı kullanılır.
Örnekler;
$ echo $(( 100 / 3 ))
33
$ myvar=”56″
$ echo $(( $myvar + 12 ))
68
#!/bin/bash
x=8
y=4
z=$(($x + $y))
echo ” $x + $y toplami= $z”
Tek mi, Çift mi Scripti
Aşağıdaki script kullanıcıdan sayı girmesini bekler ve girilen sayının tek mi, çift mi bulunduğunu bulur. Bu rahat örnekleri geliştirmek mümkündür
#!/bin/bash
number=0
echo -n “Bir sayi girini > ”
read number
echo “Girdiginiz Sayi $number”
if [ $((number % 2)) -eq 0 ]; then
echo “Girdiginiz sayi cifttir”
else
echo “Girdiginiz sayi tektir.”
fi
scripti sayi.sh olarak kaydedip çalıştıralım.
$ ./sayi.sh
Bir sayi girini > 9
Girdiginiz Sayi 9
Girdiginiz sayi tektir.
$./sayi.sh
Bir sayi girini > 24440
Girdiginiz Sayi 24440
Girdiginiz sayi cifttir
IF Şart Deyimi
Derhal her programlama dilinde kendine yer gören IF yapısı bash programlamada da karşımıza çıkıyor. Basitce bir şarta bağlı olarak program işletmeye yarayan IF yapısı scriptlerimizi daha kontrollü yazmamıza olanak sağlıyor.
Bash scriptlerindeki temel if yapısı aşağıdıdaki gibidir;
if [ şart ]
then
program_govdesi
fi
daha gelişmiş bir if yapısı ise if, elif ve else’den oluşur.
if [ koşul ]
then
komutlar
elif [ koşul2 ]
then
komutlar_2
elif [ koşul3 ]
then
..
else
komutlar_x
fi
Bu yapı ile birazcık daha gelişmiş koşullu yapılar kullanabiliriz. İlk uyan elif koşulundan sonrasında program if yapısını terkeder. Eğer if ya da elif şartlarından birine uymazsa sıra else’ye gelir ve burada verilen komut uygulanır.
Örnek;
if [ “$sayi” -eq 3 ]
then
echo “sayi 3’e esittir 3″
fi
if [ “$sbt” = “3” ]
then
echo “sbt degeri 3’dur”
fi
ilk örnekde aritmetik bir karşılaştırma yapılırken ikinci örnekte string karşılaştırması yapılıyor. String karşılaştırma işlemlerinde değişken ve karşılaştırma meydana getirilen taraf kesinlikle “ ” içinde verilmelidir, aksi takdirde hata alabilirsiniz.
İlişkisel Operatörler
Bundan önceki aritmetik if örneğinde –eq ifadesi kullandık, peki ne işe yarar bu –eq ve benzeri ifadeler? Bu ifadeler bash programlamada kullanılan hususi karşılaştırma operatörleridir ve her birinin anlamı vardır. (Ingilizce).
Aritmetik karşılaştırmalar için kullanılan bu operatörlerden bazıları ve anlamları;
-eq Eşittir
-lt küçüktür
-gt büyüktür
-ge büyük eşittir
-le minik eşittir
Dosya İlişkili Operatörler
-f file Dosya siradan bir dosya mi
-r file Dosya var ve okunabilir durumda mi
-w file Dosya var ve yazılabilir durumda mi
-x file Dosya var ve çalıştırılabilir durumda mi
-d file Hedef dosya bir dizin mi
-s file Hedef dosyanın boyutu sıfırdan büyük mü
-a VE işlemi için kullanılır.
-o VEYA işlemi için kullanılır
if [ -n “$str1” -a -n “$str2” ]
then
echo ‘ $str1 ve $str2 boştur’
fi
Örnek;
…
if [ $var = “Yes” ]
then
echo “Deger = Yes”
elif [ $var = “No” ]
then
echo “Deger= No”
else
echo “Gecersiz Deger..”
fi
Case Yapısı
Case yapısı if-then-else yapısının birazcık gelişmiş versiyonudur. Bir değişkene ilişik çoklu seçim vardır ve bu seçimlerden her biri değişik bir kıymeti temsil etmektedir. Hangi değişken şarta uyduysa o değişkenin temsil etmiş olduğu komut yürütülür. Eğer herhangi bir koşula uymazsa *) ile başlamış olan satırdaki komut devreye girer.
Case temel yapısı;
case seçenek in
durum1) komutlar ;;
durum2) komutlar ;;
durum3) komutlar ;;
*) komut_x
esac
Takvim Örneği;
Aşağıdaki script ayları ve adları eşleştirmiştir. Bu scripti geliştirip kullanıcıdan ay’ı sayı olarak girmesini isteyip karşılığını yazdırabiliriz.
#!/bin/sh
…
…
case in
01 | 1) echo “Month is January”;;
02 | 2) echo “Month is February”;;
03 | 3) echo “Month is March”;;
04 | 4) echo “Month is April”;;
05 | 5) echo “Month is May”;;
06 | 6) echo “Month is June”;;
07 | 7) echo “Month is July”;;
08 | echo “Month is August”;;
09 | 9) echo “Month is September”;;
10) echo “Month is October”;;
11) echo “Month is November”;;
12) echo “Month is December”;;
*) echo “Gecersiz Parametre!!”;;
esac
NOT: Her satırın sonuna ;; eklemezsek program uyduğu case koşulunu değil tüm koşulları ekrana basacaktır
Sayı bulmaca Scripti;
#!/bin/bash
echo -n “1 ile 3 arasinda bir sayi giriniz > “
read character
case $character in
1 ) echo “Bir girdiniz.”
;;
2 ) echo “Iki girdiniz..”
;;
3 ) echo “Uc girdiniz.”
;;
* ) echo “bir ile uc arasinda bir deger girmediniz!”
Esac
Aynı scripti if yapısı kullanarak yazmak isteseydik aşağıdaki benzer biçimde olacaktı. Her iki scripti incelersek if ile case içinde farkı daha iyi anlamış oluruz
#!/bin/bash
echo -n ” ile 3 arasinda bir sayi giriniz > ”
read character
if [ “$character” = “1” ]; then
echo “Bir Girdiniz.”
else
if [ “$character” = “2” ]; then
echo “Iki girdiniz..”
else
if [ “$character” = “3” ]; then
echo “Uc girdiniz…”
else
echo “Yanlis deger girdiniz.”
fi
fi
fi
For, while Döngüleri
Bir işi belirli sayıda ya da belirli koşula kadar yapmak için kullanılan for-while döngüleri programlama dillerinin olmazsa olmaz kalasik öğelerinden biridir. Asla unutmuyorum ilk programlama dersi aldığımız zamanlarda henuz for yapısını öğrenmemiştik ve hoca ekrana 1’den 100’e kadar sayıların çıktısını yazdırmamızı istemişti. Doğal haliyle döngü nedir bilmediğimiz için birazcık düşünüp : “ ne var bunda , alt atla yazariz demiştik”..Bir süre sonra hocamız bizim programımızı incelemeye vardığında kendisini gülmekten alamamıştı ve “Ya bine kadar yazın desem ne yapacaksınız çocuklar demişti” . Sonraki ders döngüler idi ve biz can kulağı ile dersi dinliyorduk.
Temel For yapısı;
For degisken in
Do
Komutlar..
done
Örnek;
#!/bin/bash
for aylar in Ocak Subat Mart nisan Mayis Haziran temmuz Agustos
do
echo $aylar
done
script çalıştırıldığında sırayla Ocak subat … okuyarak ekrana basacaktır.
Bir öteki örnekle mevzuyu pekiştirelim: /etc/ dizininde r ile başlamış olan tüm dosyalar listelenerelk aralarında “dizin” özelliği taşıyanlar ekrana dizin adı (dir), dizin özelliği taşımayanlar ise dosya_adi (file ) şekilde yazdırılacaktır.
#!/bin/bash
for myfile in /etc/r*
do
if [ -d “$myfile” ]
then
echo “$myfile (dir)”
else
echo “$myfile (file)”
fi
done
Sistemdeki kullanıcıları Listeleme Scripti
/etc/passwd dosyasında bulunan kullanıcıları listelemek için aşağıdaki scripti kullanabiliriz. Script içinde kullanılan awk bash benzer biçimde bir script dilidir ve script içindeki görevi /etc/passwd dosyasındaki satırları : karekterine bakılırsa ayrıştırıp ilk kolonu seçmektir.
#!/bin/bash
PASSWD_FILE=/etc/passwd
a=1
for name in $(awk -F: ‘{print }’ < “$PASSWD_FILE” )
do
echo “USER $a = $name”
let “a += 1″
done
exit 0
$chmod 700 user.sh
$./user.sh
USER #1 = root
USER #2 = daemon
USER #3 = operator
USER #4 = bin
USER #5 = smmsp
USER #6 = popa3d
USER #7 = sshd
USER #8 = _portmap
USER #9 = _identd
While , until Kullanımı
“Şart tuttuğu sürece ve şart gerçekleşene kadar işlem yap “ mantığı ile çalışan while ve Until yapısı bash altında kullanabileceğimiz döngü çeşitlerindendir.
Temel While yapısı;
while [ koşul ]
do
işlemler
done
#!/bin/bash
myvar=0
while [ $myvar -ne 10 ]
do
echo $myvar
myvar=$(( $myvar + 1 ))
done
myvar değişkeninin 0’a eşitle ve karşılaştırmaya başla, değişken 10 olmadığı müddetçe ekrana değişkenin kıymetini yaz ve kıymetini bir artır.
until while’in tam tersi denilebilir. Aşağıdaki örnekte değşkenimiz 10 olana dek ekrana yaz diyoruz.
#!/bin/bash
myvar=0
until [ $myvar -eq 10 ]
do
echo $myvar
myvar=$(( $myvar + 1 ))
done
Fonksiyonlarla işlemler
Programımız içinde sık kullanacağımız bazı yapıları bir seviye altında tanımlayarak sürekli kullanabiliriz. Örnek olarak programımız içinde kullanıcıdan veri alacak bir bölüm olsun ve biz bu kısmı birden fazla yerde kullanmak isteyelim, normalde her kullanacağımız yerde gidip aynı şeyleri yazmamız gerekecekti. Oysa bu bloğu fonksiyon olarak tanımlarsak kullanmamız ihtiyaç duyulan yerde bir tek fonksiyonu adıyla çağırmamız yeterlidir.
Temel Fonksiyon Yapısı;
Bash programlamada iki çeşit fonksiyon tanımı yapılabilir.
function fonksiyon_Adi {
komutlar
}
ya da
fonksiyon_adi () {
komutlar
}
Örnek;
#!/bin/bash
# ekrana hello yazmak için kullanılan fonksiyon
hello()
{
echo “Su an hello() fonksiyonunu cagirdiniz..”
}
echo “hello() fonksiyonu cagriliyor..”
hello
#Diger tanimlama yontemi
function hello()
{
echo “hello() fonksiyonunu cagirdiniz..”
}
NOT:Fonksiyonlar kullanılmadan ilkin tanımlanmalıdır.
Fonksiyon tanımlarken dikkat edeceğimiz bir husus. Düzgüsel dillerde fonksiyon içinde tanımlanan değişken bir tek o fonksiyon içinde geçeli olurdu. Oysa bash’de fonksiyon içinde tanımlanan değişken tüm program süresince etken olur. Bunu engellemek şu demek oluyor ki fonksiyon içinde tanımlanan değişkenin ömrünü fonksiyon ile sınırlamak istersek local değişken tanımı kullanırız.
Local degisken=”bu degisken yereldir” benzer biçimde
#!/bin/bash
Degisken=100
Function hesaplama
{
Local degisken=50
Echo -n “ Bir sayi giriniz:”
Read sayi
Echo “sayi+degisken=$(( $sayi + $degisken ))”
}
hesaplama
Scripti çalıştırılırsa ekrana “Sayi+degisken=50+girdiğiniz_değer” yazacaktır.
Fonksiyon , until karışımı bir örnek;
#!/bin/bash
function press_enter
{
echo “”
echo -n “Press Enter to continue”
read
clear
}
selection=
until [ “$selection” = “0” ]; do
echo “”
echo “PROGRAM MENU”
echo “1 – Bos Disk alanini Goruntule
echo “2 – Bos hafıza alanini Goruntule
echo “”
echo “0 – Programdan cikis
echo “”
echo -n “Seciminizi Giriniz:”
read selection
echo “”
case $selection in
1 ) df ; press_enter ;;
2 ) free ; press_enter ;;
0 ) exit ;;
* ) echo “Lutfen 1, 2, ya d a0 degerini giriniz”; press_enter
esac
done
Diziler
Diziler benzer özellikteki değişkenleri gruplamaya yarar. Örnek olarak senenin aylarını bir diziye atayarak bu diziye ay adını verirsek elimizde 12 elemanlı bir takım olur.
Aylar=(Ocak Subat Mart nisan Mayis Haziran Temmuz Agustos Eylul Ekim Kasim Aralik )
12 elemanlı bir takım. Dizilerin indisi 0’dan adım atar şu demek oluyor ki aylar dizisine bakacak olursak dizinin ilk elemanı aylar[0] ‘dır.
array=( zero one two three four five )
echo ${array[0]} # sifir
echo ${#array[*]} # 6
# dizide kac eleman oldugu