Ön Not1,
Bu makale, BASH Programming - Introduction HOW-TO makalesinin türkçe versiyonudur. Orjinali için lütfen ilgili web sayfasının ziyaret ediniz.
Ön Not2, bash scripting e hizmet etmediği düşünülen ilk bölüm tercüme edilmemiş 2. ksıımdan başlanmıştır,
2. Çok Basit Script ler
Bu döküman
sizlere, daha çok temel seviyede ve örnekler ile kabuk programlama
(shell script) hakkında ip uçları vermeyi deneyecektir. Bu bölümde
bazı küçük script'ler bulacaksınız. Umulurki kimi bazı
teknikleri anlamanıza yardımcı olacaktır.
#!/bin/bash echo Hello World
Bu script sadece
iki adet satır içeriyor. Ilki, sistemin hangi program ile bu
script'i çalıştıracağını gösteriyor. İkincisi ise, script'in
terminal'e “Hello World” yazma eylemini yapan satır oluyor. Eğer
./hello.sh şeklinde script'i çalıştırdığınızda “Command
not found” gibi bir mesaj alıyorsanız muhtemelen, ilk satır
olan “#!/bin/bash” ifadesi yanlıştır. Bu ifadenin nasıl
yazılması gerektiği konusuyla ilgili olarak bash nasıl bulunur ile
ilgili kısma bakınız.
2.2 Çok Basit bir yedek alma
script'i
#!/bin/bash
tar -cZf /var/my-backup.tgz /home/me/
Bu script'te
terminale mesaj basmak yerine kullanıcının “home” klasörü'nün
“tar” yumağı oluşturulur. Bu script kullanıma yönelik
DEĞİLDİR. Bu aşamda anlamayı kolaylaştırmak içi sunulmuş bir
örnektir.
3. “redirection” hakkında
3.1 Teori ve basit referens
stdin, stdout ve
stderr olmak üzere 3 adet dosya tanımlayıcısı vardır.
(std=Standart)
Temel olarak
şunları yapabilirsiniz,
- Stdout'u bir dosyaya yönlendirebilirsiniz.
- Stderr'ü bir dosyaya yönlendirebilirsiniz.
- Stdout'u stderr+e yönlendirebilirsiniz.
- Stderr'ü stdout'a yönlendirebilirsiniz.
- Stderr ve stdout'u bir dosyaya yönlendirebilirsiniz.
- Stderr ve stdout'u stdout'a yönlendirebilirsiniz.
- Stderr ve stdout'u stderr'e yönlendirebilirsiniz.
1, stdout'u ve 2
stderr'ü temsil eder.
Bu şeyi görmeniz
için küçük bir not: less komutu ile stdout ve stderr'ü ekrana
yazabilirsiniz ama bellek göz atmayı denediğiniz gibi silinir.
3.2 Örnek: stdout'dan dosya'ya:
Bu komutun çıktısı
ifade edilen dosyaya yazılacaktır.
ls -l > ls-l.txt
Burada ls-l.txt
ile ifade edilen dosya oluşturulacak ve “ls -l” komutunun
çıktısınından ibaret bir içeriğe sahip olacaktır.
Burada ls-l.txt
ile ifade edilen dosya oluşturulacak ve “ls -l” komutunun
çıktısınından ibaret bir içeriğe sahip olacaktır.
3.3 Örnek: stderr'den dosya'ya:
bu komutun stderr
çıktısı dosyaya yazılacaktır.
grep da * 2> grep-errors.txt
grep-errors.txt
ismi ile ifade edilen dosya oluşturulacak ve içeriği “grep da
*2” komutunun stderr çıktısından ibaret bir içeriğe sahip
olacaktır.
3.4 Örnek: stdout'dan stderr'e:
grep da * 1>&2
Yani komutun
stdout çıktısını stderr'e gönderir.
3.5 Örnek: stderr'den stdout'a:
komutun stderr
çıktısını stdout a gönderir. Eğer “|” ile “less” less
çalıştırırsanız bu kes çıktıyı yakalarsınız çünkü bu
kez bilgi stdout'dadır. Normalde less ile stderr çıktısını
yakalayamıyor, gözden kaçırıyorduk.
3.6 Örnek: stderr ve stdout'dan
dosya'ya:
Bu her çıktıyı
dosyaya gönderecektir. Eğer komutun sessiz kalmasını istiyorsanız
bu yöntem cron uygulamarından olduğu gibi bazen daha uygun
olabiliyor.
rm -f $(find / -name core) &> /dev/null
bu komut core ismi
ile anılan her dosya ve klasörü silecektir. Bunu yapmak
istediğinizden oldukça emin olmanız gerekir. Her silme işminin
çıktısı da silinecektir.
4. PIPE (“|”):
Bu bölümde “|”
kullanımına basit örnekler verip nasıl kullanıldığını
gösterecek, onu neden kullanmak istediğimizi anlayacağız.
4.1 Nedir?
Bir komutun
çıktısını diğer bir komuta girdi yapar.
4.2 Örnek: sed 'in pipe ile basit kullanımı:
4.2 Örnek: sed 'in pipe ile basit kullanımı:
ls -l | sed -e "s/[aeio]/u/g"
ls -l komutu ile
bulunduğumuz klasörün içeriğini “permission” ları ile
bbirlikte uzun formatta listeleriz ve bu sonuç çıktısını “sed”
komutunu göndeririz. “sed” komutu ise kendisine parametreleri
ile söylendiği gibi “a,e,i,o” karakterlerini gördüğü
yerleri “u” karakteri ile değiştirir.
4.3 Örnek: “ls -l *.txt” komutu
için bir alternatif:
Muhtemelen, bu
yöntem “ls -l *.txt” yönteminden daha kolay değildir ancak
pipe'ın kullanımı görmek için iyi bir örnektir.
ls -l | grep "\.txt$"
yine “ls -l
komutunun çıktısı “grep” komutuna girdi olarka gönderilir ve
“ls -l” çıktısı metni içinde “grep” ile ifade edilen
metin aranır. Eşleşen satırlar enrana basılır.
5. Değişkenler:
Değişkenleri,
diğer bütün programlama dillerindeki gibi kullanabilirsiniz. Veri
tipi yoktur. Bash değişkenleri numaraları, karakterleri ve
karakter dizilerini içerebilirler. Önceden değişkenleri bildirmek
zorunda değilsinizdir. Bir değer atanırken kendileri de zaten
oluşturulmuş olurlar.
5.1 Örnek: Değişken kullanarak
Hello World! yazmak:
#!/bin/bash STR="Hello World!" echo $STR
İkinci satırda
string tipinde “Hello World!” değerine sahip “STR” adında
bir değişken tanımlanmıştır. Bu değişkenin değerine ulaşmak
istediğimizde değişken adının başına “$” eklenecektir.
Başına $ işareti koymadığınızda nasıl bir durumla
karşılaşacağınızı deneyiniz lütfen.
5.2 Örnek: Çok
basit bir yedek alma script'i (biraz daha iyi):
#!/bin/bash OF=/var/my-backup-$(date +%Y%m%d).tgz tar -cZf $OF /home/me/
Bu script başka
bir şeyi daha tanıtır. Herşeyden önce yine ikinci satırda
değişken kullanımına örnek oluşturur. Ve '$(date
+%Y%m%d)' ifadesi. $ ve parantez ifadesi ile, parantez içerisindeki
komutun çıktısı yakalanır ve değişkenin toplam değerinin
üretilmesine katkı sağlatılır.
Bu komutun çıktısı
her gün (+%Y%m%d) ifadesindeki formata göre farklı bir değer
döndürür. Bu kısım ile oynayarak farklı formatlar elde
edebilirsiniz. Daha fazlası için “date” komtu kullanımına
bakınız.
“$” ve
parantez kullanımı anlamak için komut satırında aşağıdaki şu
iki ifadeyi çalıştırmayı deneyin:
echo ls echo $(ls)
5.3 Yerel Değişkenler:
Bir
fonksiyon gibi sadece yerel bir alanda geçerli olan
değişkenkenlerdir.
#!/bin/bash HELLO=Hello function hello { local HELLO=World echo $HELLO } echo $HELLO hello echo $HELLO
Bu
örnek, yerel değişkenleri anlamak yeterli bir örnek olmalı.
Şartlar
bir ifadenin bir eylemi icra edilip edilmeyeceğini kararının
verilmesini sağlayan yapılardır.
6.1
If / Else Yapıları
Şartların
farklı formları vardır. En temel formu, IF “kontrol
ifadesi” THAN “uygulanacak ifade” şeklindedir. Eğer
kontrol ifadesi doğru ise, uygulanacak ifade kısmı işletilir,
değil ise işletimeden atlanır. “2<1” yanlış bir ifade,
“2>1” ise doğru bir ifadedir.
Şartlar
için diğer bir ifade formu ise, IF “kontrol ifadesi”
THAN “uygulanacak ifade 1” ELSE “uygulanacak
ifade 2” şeklindedir. Kontrol ifadesi doğru ise, “uygulanacak
ifade 1” işletilir yanlış ise, “uygulacak ifade 2”
işletilir.
Bir
başka şartlar formu ise, IF “kontorl ifadesi 1” THAN
“uygulacak ifade 1” ELSE IF “kontrol ifadesi 2” THAN
“uygulacak ifade 2” ELSE “uygulacak ifade 3”
şeklindedir. Bu çart forumda ise farklı olarak ELSE IF
kullanılmıştır. Bununla ilk kontrol ifadesinin yanlış olması
durumunda ikinci bir kontrol ifadesinin doğruluğu kontrol edilmiş
oluyor.
Bash'de
IF in temel yazımı;
#!/bin/bash if [kontrol ifadesi]; then kontrol ifadesi doğru ise çalıştırılacak olan CODE fi
6.2
Örnek: Temel şartlar örneği, if..then
#!/bin/bash if [ "foo" = "foo" ]; then echo expression evaluated as true fi
Eğer
parantezler arasındaki ifade doğru ise then ile fi arasındaki code
işletilecektir.
6.3
Örnek: Temel şartlar örneği, if..then..else
#!/bin/bash if [ "foo" = "foo" ]; then echo expression evaluated as true else echo expression evaluated as true fi
6.4
Değişkenlerle Şartlar,
#!/bin/bash T1=”foo” T2=”bar” if [ "T1" = "T2" ]; then echo expression evaluated as true else echo expression evaluated as true fi
7.
Döngüler; for, while ve until
Bu
bölümde for, while ve until döngülerine yer verilecektir.
For
döngüleri küçük bir fark gösterir diğer programlama
dillerinden. Temel olarak kelimelerin bir dizi üzerinden
tekrarlanmaları şeklindedir.
While
döngüleri ise kontrl ifadesi doğru olduğu sürece kodu tekrar
tekrar işletirler.
Until
döngüleri ise nerdeyse while döngüleri gibidir. Sadece kontrol
ifadesinin doğru olduğu durum boyunca değil, yanlış olduğu
sürece kodu işletirler.
7.1
FOR örneği
#!/bin/bash for i in $( ls ); do echo item: $i done
İkinci
satırda i ifadesi ile bir değişken bildirimi yapılır ki bu
değişken döngü boyunca ls 'in farklı farklı değerlerini
alacaktır. Üçüncü satır ise gerekirse daha uzun olabilir,
birden fazla satır ile de ifade edilebilir. Bu bölüm “ -done-
ifadesine kadar “ şeklinde tanımlanan bölümdür. Done ifadesi
ile döngü biter ve $i yeni bir değer alabilir.
7.2
C dilindeki gibi FOR örneği
#!/bin/bash for i in `seq 1 10`; do echo $i done
7.3
While örneği
#!/bin/bash COUNTER=0 while [ $COUNTER -lt 10 ]; do echo The counter is $COUNTER let COUNTER=COUNTER+1 done
7.4
Until örneği
#!/bin/bash COUNTER=20 until [ $COUNTER -lt 10 ]; do echo The counter is $COUNTER let COUNTER-=1 done
8.
Fonksiyonlar
Hemen
her programla dilince fonksiyonları kullanabilir ve onlar ile
program kodlarını mantıksal olarak bölebilir ya da pratiklik
kazandırabilirsiniz.
Fonksiyonu
tanımlama / belirleme için kısaca my_func { my_code } şeklinde
yazabilir ve kullanmak için ise sadece adını yazabiliriz.
8.1
Fonksiyon örneği
#!/bin/bash function quit { exit } function hello { echo Hello! } hello quit echo foo
2-4
arası satırlar quit fonksiyonunu ve 5-7 arasındaki satırlar ise
hello fonksiyonunu tanımlamaktadırlar. Bu kısmında fonksiyonların
ne şekilde sıralandıklarını bir önemi yoktur. Sekizinci satırda
hello fonksiyonu işletilecek ve dokuzuncu satırda exit fonksiyonu
işletilecek, bu esnada script'den çıkılacak ve bu sebeple hiç
bir zaman onuncu satır işletilmeyecektir.
8.2
Fonksiyonların parametre alması
#!/bin/bash function quit { exit } function e { echo $1 } e hello e world quit echo foo
Bu
script de bir önceki ile nerdeyse aynıdır, tek farkı e
fonksiyonu!. E fonksiyonu parametre almaktadır. Sekizinci satırda
“hello” parametresini alır ve ekrana bu parametreyi yazar, aynı
fonksiyon dokuzuncu satırda world parametresini alır ve bu kez
world ifadesini yazar. Onuncu satırda exit fonksiyonu işletilere
script'den çıkılır ve onbirinci satır hiç bir şekilde
işletilmeye fırsat bulamaz.
9.
Arabirim kullanımı
9.1
select kullanarak basit menu yapımı
#!/bin/bash OPTIONS=”Hello Quit” select opt in $OPTIONS; do if [ "$opt" = "Quit" ]; then echo done exit elif [ "$opt" = "Hello" ]; then echo Hello World else clear echo bad option fi done
Yukarıdaki
script'i çalıştırdığınızda bir text menu göreceksiniz.
9.2
Komut satırının kullanımı
#!/bin/bash if [ -z "$1" ]; then echo usage: $0 directory exit fi SRCD=$1 TGTD="/var/backups/" OF=home-$(date +%Y%m%d).tgz tar -cZf $TGTD$OF $SRCD
Sanırım
yukarıdaki script daha anlaşılır ve fonksiyonel oldu. Kısaca
açıklayalım;
script'i
sadece adını yazarak çalıştırırsanız, “echo usage:
[script'in adı] directory” şeklinde bir uyarı alırız. Bu,
script'in adını yazdıktan sonra backup'ını alacağımız
klasörün full-path'ini belirtmemiz gerektiği söyleyen bir
uyarıdır. Örneğin script'in adı, ornekci.sh ise ve yedeğini
alacağımız klasör de /home/kullanici/yedeginial klasörünü ise:
“yedekci.sh home/kullanici/yedeginial” komutunu kullanmalıyız.
Bu durumda script, adı home-”tarihifadesi”.tgz isminde bir
backup dosyası oluşturacaktır.
10.
Diğer
10.1
Read ile kullanıcı girdisini okumak
Bir
çok durumda programcı programını kullanan kullanıcıdan girdi
almak ister. Buna ulaşmanın birden fazla yolu vardır ki bunlardan
birisi ise “read” kullanmaktır. Basit bir örneği aşağıdaki
gibidir;
#!/bin/bash echo Please, enter your name read NAME echo "Hi $NAME!"
Aşağıdaki
örnekte olduğu gibi birden çok girdi ifadesini tek bir read satırı
ile de okuyabilirsiniz;
#!/bin/bash echo Please, enter your firstname and lastname read FN LN echo "Hi $FN, $LN !"
10.2 Aritmetik işlemler
Aşağıdaki
ifadeyi komutsatırında işletiniz,
echo 1 + 1
Eğer
2 görmeyi bekliyor idiyseniz, düşkırıklığına uğramış
olmalısınız. 2 sonucunu görmek için çözüm şu şekilde
olmalıydı:
echo $((1+1))
Bu
daha mantıksal bir sonuç verecektir. Bu işlem aritmetik bir bir
ifade oldu. Bir başka şekilde;
echo $[1+1]
İfadesiyle
de aynı sonuca ulaşabilirsiniz.
Eğer
küsüratlara ihtiyacınız var ise, durum biraz farklıdır. Meslea,
echo $[3/4]
ifadesini
denerseniz “0” sonucunu görürsünüz zira, bash her zaman
integer yani tam sayı sonuçlar verir. Küsüratı görmek için
çözüm,
echo 3/4|bc -l
komutunu kullanmalısınız. Bu durumda 0.75 sonucuna ulaşılabilir.
10.3
Bash'i bulmak.
(Mike
'dan gelen mesaja istinaden dökümana eklenmiş kısımdır.
Kendisine teşekkür..)
betik
yolu olarak sürekli “#!/bin/bash” kullandık ama olaki farklı
sistemlerde bash'in yolu farklı olabilir. Dolayısıyla nerede
olduğunu tespit gerekebilir. Bunun için en ideal komut “locate”
dir. “locate bash” komutunu çalıştırarak bash'i bulabiliriz.
Ancak bazı sistemlerde locate komutu yer almayabilir. Bu durumda
“find ./ -name bash” ile (bence işi garantiye almak için “find
/ -name bash” kullanmak daha faydalı olacaktır. Zira ./ ifadesi
“relative path” dir ve doğruluğu “current path” e bağlıdır.
Oysa / ifadesi absolute path dir ve doğruluğu hiç bir şeye bağlı
değildir. Yani her zaman doğrudur.) ile bash'in yeri tespit
edilebilir. Varlığını kontrol etmek için önerilen yollar;
ls -l /bin/bash ls -l /sbin/bash ls -l /usr/local/bin/bash ls -l /usr/bin/bash ls -l /usr/sbin/bash ls -l /usr/local/sbin/bash
ya
da “which bash” komutu ile bash 'in yolu araştırılabilir. (ya
da “whereis” ile)
10.4
Geri döndürülen değeri (return value) yakalamak.
Bash
kabuğu script'dekıi bir komutun geri döndürdüğü değeri $? ile
gösterilen özel bir değişkende depolar. Bu değer nasıl
yakalayabileceğimizi aşağıdaki örnek daha iyi açıklar. Bu
örnekte olmana bir “dada” klasörüne girmeye çalışıyoruz ve
geri döndürülen bir hata mesajını yakalamak istiyoruz. (bu da
Mike'ın önerisi ile)
#!/bin/bash cd /dada &> /dev/null echo rv: $? cd $(pwd) &> /dev/null echo rv: $?
10.5
Komut çıktısını yakalamak.
Bu
küçük script ise ilgili mysql veri tabanındaki tüm tabloları
listeler,
#!/bin/bash DBS=`mysql -uroot -e"show databases"` for b in $DBS ; do mysql -uroot -e"show tables from $b" done
10.6
Çoklu dosya kaynakları
Komut
kaynağı ile birlikte çoklu dosya kullanabilirsiniz.
__TO-DO__
11.
Tablolar
11.1
String karşılaştırma operatörleri
(1)
s1 = s2
(2)
s1 != s2
(3)
s1 < s2
(4)
s1 > s2
(5)
-n s1
(6)
-z s1
(1)
s1 matches s2
(2)
s1 does not match s2
(3)
__TO-DO__
(4)
__TO-DO__
(5)
s1 is not null (contains one or more characters)
(6)
s1 is null
11.2
String karşılaştırma örnekleri
iki
string'in karşılaştırılması,
#!/bin/bash S1='string' S2='String' if [ $S1=$S2 ]; then echo "S1('$S1') is not equal to S2('$S2')" fi if [ $S1=$S1 ]; then echo "S1('$S1') is equal to S1('$S1')" fi
11.3
Aritmetik operatörler
+
-
*
/
%
(remainder)
11.4
Aritmetik karşılaştırmak operatörleri
-lt
(<)
-gt
(>)
-le
(<=)
-ge
(>=)
-eq
(==)
-ne
(!=)
C
programcıları parantez içindeki ifadeleri kullanırlar,
11.5
Kullanışlı Komutlar,
Bu
bölüm Kess tarafından tekrar yazılmıştır. (Kendisine
teşekkür..)
sed
(stream editor)
Örnekler,
(aşağıdaki komutları test ediniz;)
$sed 's/to_be_replaced/replaced/g' /tmp/dummy $sed 12, 18d /tmp/dummy
awk
(metin editleme işlemi yapar) (mawk, gawk gibi versiyonları da
vardır.)
dummy
dosyasının içeriği aşağıdaki gibi ise,
"test123 test tteesstt"
aşağıdaki
komutları sırasıyla test ediniz ve her adımda dosyayı kontrol
ediniz.
$awk '/test/ {print}' /tmp/dummy $awk '/test/ {i=i+1} END {print i}' /tmp/dummy
grep
(bir metin içindeki aranan satırları ekrana basar)
$grep "look for this" /var/log/messages -c
wc (word count)
$wc --words --lines --bytes /tmp/dummy
sort
(satırları sıraya sokar)
$sort /tmp/dummy
bc
(hesaplama programlama dili)
$bc -q
tput
(initialize a terminal or query terminfo database)
$tput cup 10 4 $tput reset $tput cols
12.
Daha fazlası
12.2
Örnek: Çok basit bir yedekleme script'i,
#!/bin/bash SRCD="/home/" TGTD="/var/backups/" OF=home-$(date +%Y%m%d).tgz tar -cZf $TGTD$OF $SRCD
12.3 Dosya ismi değiştiricisi,
#!/bin/sh # renna: rename multiple files according to several rules # written by felix hudson Jan - 2000 #first check for the various 'modes' that this program has #if the first ($1) condition matches then we execute that portion of the #program and then exit # check for the prefix condition if [ $1 = p ]; then #we now get rid of the mode ($1) variable and prefix ($2) prefix=$2 ; shift ; shift # a quick check to see if any files were given # if none then its better not to do anything than rename some non-existent # files!! if [$1 = ]; then echo "no files given" exit 0 fi # this for loop iterates through all of the files that we gave the program # it does one rename per file given for file in $* do mv ${file} $prefix$file done #we now exit the program exit 0 fi # check for a suffix rename # the rest of this part is virtually identical to the previous section # please see those notes if [ $1 = s ]; then suffix=$2 ; shift ; shift if [$1 = ]; then echo "no files given" exit 0 fi for file in $* do mv ${file} $file$suffix done exit 0 fi # check for the replacement rename if [ $1 = r ]; then shift # i included this bit as to not damage any files if the user does not specify # anything to be done # just a safety measure if [ $# -lt 3 ] ; then echo "usage: renna r [expression] [replacement] files... " exit 0 fi # remove other information OLD=$1 ; NEW=$2 ; shift ; shift # this for loop iterates through all of the files that we give the program # it does one rename per file given using the program 'sed' # this is a sinple command line program that parses standard input and # replaces a set expression with a give string # here we pass it the file name ( as standard input) and replace the nessesary # text for file in $* do new=`echo ${file} | sed s/${OLD}/${NEW}/g` mv ${file} $new done exit 0 fi # if we have reached here then nothing proper was passed to the program # so we tell the user how to use it echo "usage;" echo " renna p [prefix] files.." echo " renna s [suffix] files.." echo " renna r [expression] [replacement] files.." exit 0 # done!
12.4
Dosya ismi değiştiricisi (basit)
#!/bin/bash # renames.sh # basic file renamer criteria=$1 re_match=$2 replace=$3 for i in $( ls *$criteria* ); do src=$i tgt=$(echo $i | sed -e "s/$re_match/$replace/") mv $src $tgt done
13.
Bazı şeyler yanlış giderse (debugging – hata ayıklama)
13.1
BASH çağırma yöntemleri
script'in
ilk satırını aşağıdaki gibi yazarsak,
#!/bin/bash -x
bu
bize bazı ilginç çıktılar verecektir.
14.
Döküman Hakkında
14.1
Herhangi bir garanti vaat etmez!
Bu
dökümanda anlatılanlar herhangibir garanti vaat etmez.
14.2
Çerviriler
ORJINAL
VERSIYON: http://www.tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html
Italian:
by William Ghelfi (wizzy at tiscalinet.it) is here /
http://web.tiscalinet.it/penguin_rules
French:
by Laurent Martelli
Korean:
Minseok Park http://kldp.org
Korean:
Chun Hye Jin
Spanish:
unknow http://www.insflug.org
Hiç yorum yok:
Yorum Gönder