1) Girdi – Çıktı İşlemleri
Linux ortamında 1 adet girdi ortamı, 2 adet de çıktı ortamı bulunmaktadır. Bu ortamlar aşağıdaki gibi listelenebilir.
- Standart Girdi (0): Kullanıcının giriş yaptığı ortamdır. Klavye standart giriş noktası olarak kullanılır. Kullanıcıdan alınan değer bir değişkene atanarak kullanılabilir.
1 |
read -p "Bir ifade giriniz:" kelime |
- Standart Çıktı (1): Başarılı bir işlem sonucunun aktarıldığı ortamdır. Monitor standart çıkış noktası olarak kullanılır. İstenirse başarılı durumlar başka bir ortama (dosya gibi) da aktarılabilir.
1 |
cat /etc/passwd 1>/var/log/olaylogu |
- Hata Çıktısı (2): Başarısız bir işlem sonucunun aktarıldığı ortamdır. Monitor standart çıkış noktası olarak kullanılır. İstenirse başarısız durumlar başka bir ortama (dosya gibi) da aktarılabilir. “/dev/null” kara delik olarak da adlandırılabilir ve çöp kutusu olarak kullanılabilir.
1 2 |
cat /etc/passwdd 2>/var/log/hatalogu cat /etc/passwdd 2>/dev/null |
1 |
cat /etc/passwdd &>/var/log/olayvehatalogu |
- Gri: 30
- Kırmızı: 31
- Yeşil: 32
- Sarı:33
- Mavi:34
- Magenta:35
- Cyan:36
1 |
echo -e "\e[1;34mMerhaba! Mavi renkli bir yazi \e[0m" |
2) Değişken İşlemleri
Veri tipinden bağımsız olarak atama işlemi gerçekleştirilebilir. Örnek atama işlemleri aşağıdaki gibidir.
1 2 3 4 |
sayi=7 karakter="7" bosKelime="" kelime="Ahmet" |
Not: Değişkenlere atama yaparken atanacak değeri iki adet çift tırnak (“…”) içine almak karşılaşılabilecek hataların önüne geçebilir.
Betiğe veya fonksiyona verilen bir parametre (ilk parametre için $1, ikinci paramtre için $2,… gibi) başka bir değişkende saklanabilir.
1 |
geciciDegisken=$1 |
Katar ifadeler birleştirilebilir.
1 |
kelime=$kelime$ek |
Sayılar ile dört işlem gerçekleştirilebilir.
1 2 3 4 5 6 |
sayac1=20 sayac2=$((32-$sayac1)) sayac2=$(($sayac2 + 1)) let sayac1=sayac1+1 let sayac2-=1 let "carpim=$sayac1*$sayac2" |
Komut sonucunu bir değişkene atama işlemi “$(KOMUT)” veya “KOMUT
” ile gerçekleştirilebilir. Örneğin:
1 2 |
Dosyalar1=$(ls -l /tmp) Dosyalar2=`ls -l /tmp` |
Geçici olarak bir dosya oluşturularak dosyanın yolu bir değişkene atanabilir. “mktemp” komutu belirtilen dizinde o dosyanın olmadığını garanti eder
1 |
ciktiDosyasi=$(mktemp /tmp/$USER.XXXX) |
Değişkeni kullanmak için başına dolar ($) işareti konulur.
1 |
echo $Degisken |
Bir değişkenin başka kabuklarda da kullanılması isteniyorsa çevre değişkeni olarak tanımlanmalıdır. Çevre değişkenleri “env” komutu ile liftelenebilir. Bu komutun örnek çıktısı:
1 2 3 4 5 6 7 8 9 10 11 |
SHELL=/bin/bash SSH_TTY=/dev/pts/3 USER=root PATH=/root/Desktop/Uygulamalar:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PWD=/root HOME=/root LANGUAGE=en_US:en LOGNAME=root SSH_CONNECTION=192.168.30.1 61105 192.168.30.133 22 XDG_RUNTIME_DIR=/run/user/0 _=/usr/bin/env |
Bir komutu çalıştıran kullanıcıya ait bazı bilgiler (komutu çalıştıran kullanıcının kabuğu veya adı gibi) bu değişkenler ile elde edilebilir.
1 2 |
echo $SHELL echo $USER |
Araçların veya betiklerin bulunduğu belli bir dizin varsa, bu dizinin çevresel değişkenlere atanması “export” komutu ile gerçekleştirilebilir. Geçici olarak PATH‘e dizin atama işlemi için aşağıdaki komut kullanılabilir.
1 |
export PATH=/home/hesap/Desktop/betikler/:$PATH |
Kalıcı değişken atamak için “.bashrc” dosyasına eklenmelidir. Tüm “.bashrc” dosyaları için “locate .bashrc” komutu kullanılabilir.
1 2 |
/etc/bash.bashrc ~/.bashrc |
3) if-elif-else ile Karşılaştırma
Temel kullanım aşağıdaki gibidir. Köşeli parantez (“[” ve “]”) karakterlerinden önce boşluk olmalıdır.
1 2 3 4 5 6 7 8 9 10 |
if [ $sayi == "1" ] then echo "Sayı: 1" elif [ $sayi == "2" ] then echo "Sayı: 2" else echo "Sayı 1 veya 2 değil" exit 1 fi |
Tek satırda gösterimi aşağıdaki gibidir.
1 |
if [ ŞART1 ]; then İŞLEM1; elif [ ŞART2 ]; then İŞLEM2; else İŞLEM3; fi |
“if” ifadesinden sonraki kısım ( yani “[ ŞART ]” şeklindeki bölüm) boolean olabilir.
Betiklerde en sık kullanılan ifadeler aşağıdaki gibidir:
1 2 3 |
[ $? -eq 0 ] # Önceki komut doğru çalıştırılmışsa [ $# -eq 3 ] # Parametre sayısı 3 ise [ ! -z $1 ] # Birinci parametre boş değilse |
Kelimeler (string ifadeler) için “==”, “!=” kullanılır.
1 2 3 4 |
[ "$Kelime" == Test ] # "Kelime", "Test" ise [ "$Kelime1" != "$Kelime2" ] # Kelimeler bir birinden farklıysa [ ! -z $Kelime ] # Kelime boş değilse [ "$Kelime1" < "$Kelime2" ] # Szölük sırasına göre Kelime1, Kelime2'den önce geliyorsa |
Sayılar için “-eq”, “-lt”, “-gt”, “-le”, “-ge”, “-eq”, “-ne” … kullanılır.
1 2 3 |
[ $Kilo -le $Boy ] # "Kilo", "Boy"'dan küçük eşitse [ ! $Sayi == 2 ] # Sayı 2 değilse [ $Sayi -eq "0" ] # Sayı 0 ise |
Not: Eğer şart ifadesinin yazılacağı alanda “[]” yerine “()” kullanılıyorsa “==” da kullanılabilir.
1 2 3 4 |
(( $Sayi1 == $Sayi2 )) (( $Sayi1 >= $Sayi2 )) (( $Sayi1 < $Sayi2 )) (( $Sayi % 5 == 0 )) |
Linux işletim sistemlerinde her şey dosyadır. Dosya işlemler için aşağıdaki ifadeler kullanılabilir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
[ -f $DosyaAdi ] # Dosya varsa [ -a $DosyaAdi ] # Dosya varsa [ -e $DosyaAdi ] # Dosya varsa [ -O $DosyaAdi ] # Dosya var ve sahibi betiği çalıştıransa [ -G $DosyaAdi ] # Dosya var ve sahibi betiği çalıştıranın grubuysa [ -r $DosyaAdi ] # Dosya var ve komutu çalıştıran kullanıcının dosyayı okuma yetkisi varsa [ -w $DosyaAdi ] # Dosya var ve komutu çalıştıran kullanıcının dosyayı yazma yetkisi varsa [ -x $DosyaAdi ] # Dosya var ve komutu çalıştıran kullanıcının dosyayı çalıştırma yetkisi varsa [ -s $DosyaAdi ] # Dosya var ve boyutu 0'dan büyükse (boş değilse) [ -S $DosyaAdi ] # Dosya var ve bir soketse [ -k $DosyaAdi ] # Dosya var ve StickyBiti set edilmişse [ -u $DosyaAdi ] # Dosya var ve Suid biti set edilmişse [ -d $DosyaAdi ] # Dosya bir dizin ise [ -h $DosyaAdi ] # Dosya sembolik bağlantı ise [ -l $DosyaAdi ] # Dosya sembolik bağlantı ise [ $DosyaAdi1 -ef $DosyaAdi2 ] # Dosyalar aynıysa (Nesne ID değeri olarak) |
Düzenli ifadelerde köşeli parantezler çiftleştirilir. Yani iki adet “[[” ve “]]” kullanılır.
1 2 3 |
[[ “$Kelime” == *Tes* ]] [[ -a *.sh ]] # ".sh" uzantılı dosya varsa [[ $Sayi -eq 3 && “$Kelime” == Test ]] # "&&" ve; "||" ifadelerinde köşeli parantezler çiftleştirilir. |
Bir fonksiyon çıktısına göre de sorgulama yapılabilir.
1 |
! proses_calisiyor_mu |
Köşeli parantez kullanılmadan da “if” sorguları gerçekleştirilebilir.
1 2 |
grep ^$Kelime /root/Dosya 1> /dev/null # "Kelime" belirtilen dosyada varsa ! grep ^$Kelime /root/Dosya 1> /dev/null # "Kelime" belirtilen dosyada yoksa |
Sorgulama işlemi için “test” komutu da kullanılabilir. “test” komutundan sonra “if [ $? -eq 0 ]” sorgusu ile “test” komut çıktısının doğruluğu kontrol edilebilir.
1 2 3 |
test "$Parola" = "Aa123456" # Parola değeri "Aa123456" ise test $Sayi -ge 0 # Sayı 0'dan büyük eşitse test ! -f "$DosyaAdi" # Dosya yoksa |
4) case-esac ile Karşılaştırma
if-elif-else yapısındaki gibi karşılaştırma işlemleri gerçekleştirilebilir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
case $Sayi in 1) echo "Bir" ;; 2) echo "İki" ;; [3-5]*) echo "Üç Dört veya Beş" ;; *) echo "Bilinmiyor" ;; esac |
Kelimeler için de karşılatırma gerçekleştirilebilir.
1 2 3 4 5 6 7 8 |
case $Kelime in Kirmizi) echo "Dur..." Sari) echo "Hazir Ol..." Yesil) echo "Geç..." esac |
5) for Döngüsü
Döngüler sayıları birer birer arttırmak için kullanılabilir.
1 2 3 4 |
for sayac in `seq 1 255` do ping -c 1 192.168.2.$sayac done |
Aynı işlem tek satırda da gerçekleştirilebilir.
1 |
for sayac in $(seq 1 254); do ping -c 1 192.168.2.$sayac; done; |
Sayıları birer birer arttırmak için kullanılabilir (Yöntem – 2)
1 |
for (( sayac=1; sayac<=255; sayac++ )) |
Sayıları birer birer arttırmak için kullanılabilir (Yöntem – 3)
1 |
for sayac in {1..255} |
Tek satırda gösterimi aşağıdaki gibidir:
1 |
for [ ŞART ]; do İŞLEM1; İŞLEM2; İŞLEM3; done |
Sayıları üçer üçer arttırmak için kullanılabilir. Aşağıdaki döngü 1,4,7,… şeklinde devam eder.
1 |
for sayac in {1..255..3} |
Çoklu kontrol de gerçekleştirilebilir.
1 |
for ((a=1, b=1; a <= $UST_SINIR ; a++, b++)) |
Bir dosya içerisinde dolaşılabilir.
1 |
for satir in `cat $DOSYA` |
“for” kullanıldığında liste içerisindeki ifadeler yeni satıra göre değil, boşluk karakterine göre ele alınır.
1 2 |
cumle='Ali ata bak' for kelime in $cumle |
Not: Eğer satır satır ele alınmak isteniyorsa “while” kullanılmalıdır.
Bir dizi içerisinde dolaşılabilir.
1 |
for meyve in "elma" "armut" "portakal" "muz" "cekirdeksiz uzum" "incir" |
Sonsuz döngü oluşturulabilir.
1 |
for (( ; ; )) |
Bir dosyalar dizisi içerisinde işlemler gerçekleştirilebilir.
1 2 3 4 |
DOSYALAR="/etc/passwd /etc/shadow /usr/sbin/chroot /etc/samba/smb.conf" |
Her bir dosya için işlem yapılmak istenebilir.
1 |
for dosya in $DOSYALAR |
Her dosyanın içerisindeki uygun değer ekrana bastırılabilir.
1 |
for dosya in `cat $DOSYALAR` |
Her bir sayı tek tek ele alınabilir.
1 2 |
SAYILAR="9 7 3 8 37.53" for sayi in `echo $SAYILAR` |
Bulunulan dizinde belirli bir formattaki dosyalarda dolaşılabilir.
1 |
for dosya in [passw]* |
Belirtilen dizinde belirli bir formattaki dosyalarda dolaşılabilir.
1 |
for dosya in /etc/*.conf |
Not: Döngüden çıkmak için “break” komutu kullanılır. Mevcut iterasyondan çıkıp, sonraki iterasyona devam etmek için ise “continue” komutu kullanılır.
6) while Döngüsü
Döngüler belirli bir şart sağlanana dek devam edebilir.
1 2 3 4 5 6 7 |
sayac=0 UST_LIMIT=10 while [ "$sayac" -lt "$UST_LIMIT" ] do sayac=$(($sayac + 1)) echo $sayac done |
Dosya içerisinde satır satır dolaşılabilir.
1 2 3 4 |
cat $Dosya | while read -r satir do echo $satir done |
Not: Dosya içerisindeki ifadeler satır satır ele alınır. boşluk karakterine göre ele alınmak isteniyorsa “for” kullanılmalıdır.
Dosyada dolaşılabilir (Yöntem – 2):
1 2 3 4 |
while IFS=, read -r satir do echo $satir done < $Dosya |
Bir komut çıktısındaki her satır tek tek elde edilebilir.
1 |
ls -1 | grep passwd | while read satir; do echo "$satir"; done |
Tek satırda gösterimi aşağıdaki gibidir:
1 |
while [ ŞART ]; do İŞLEM1; İŞLEM2; İŞLEM3; done |
Sonsuz döngü oluşturulabilir.
1 2 |
while [ true ] # Sonsuz döngü while [ 1 ] # Sonsuz döngü |
Döngüyü belirten kısım ( yani “while [ ŞART ]” şeklindeki ifadeler) aşağıdaki gibi belli bir değere ulaşana dek de beklenebilir.
1 2 |
while [ "$kelime" != "son" ] while (( $sayac <= $UST_SINIR )) |
Not: Döngüden çıkmak için “break” komutu kullanılır. Mevcut iterasyondan çıkıp, sonraki iterasyona devam etmek için ise “continue” komutu kullanılır.
7) until Döngüsü
Sayıları birer birer azaltmak için kullanılabilir.
1 2 3 4 5 |
sayac=10 until [ $sayac -lt 3 ]; do echo $sayac let sayac-=1 done |
Döngüyü belirten kısım ( yani “until [ ŞART ]” şeklindeki ifadeler) aşağıdaki gibi olabilir.
1 2 |
until [ "$kelime" != "son" ] until (( $sayac <= $UST_SINIR )) |
8) Betikler ve Fonksiyonlar
Bash ile bir program hazırlanırken öncelikle “bash” in lokasyonu belirtilmelidir.
1 |
#!/bin/bash |
Betiği taşınabilir yapmak için betik başına “bash” lokasyonu için “env” değişkeni ile beraber aşağıdaki gibi kullanılabilir.
1 |
#!/usr/bin/env bash |
Bir betiği çalışabilir hale getirmek için chmod aracı kullanılabilir
1 2 |
chmod +x betik.sh chmod 744 betik.sh |
Örnek bir betik (betik.sh) ve fonksiyon (yazdir) içeriği aşağıdaki gibidir. Fonksiyonu 3 parametre gönderilmiştir. “$1” ile belirtilen değişken betiğin ilk parametresidir. Betiğin çıktısı: <Merhaba Ahmet. Nasilsin?> olacaktır.
1 2 3 4 5 6 |
#!/usr/bin/env bash karsilama="Merhaba" function yazdir(){ echo "$1 $2. $3?" } yazdir $karsilama $1 "Nasilsin" |
Not: Bash programlamada fonksiyon çağırılacaksa, önce fonksiyon tanımlanmalı, sonrasında çağırma işlemi gerçekleştirilmelidir.
Bu betiği çağırırken betik adı ve parametreleri verilebilir.
1 |
./betik.sh Ahmet |
Paralel çalışacak şekilde bir fonksiyon aşağıdaki gibi hazırlanabilir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
function tarama() { curl -I "$KurbanUrl" } while HedefIP -r Dosya do prosesAdedi=$(ps -ef | grep -v grep | grep -Eq "curl -I" | wc -l) url="http://$HedefIP" while [ 1 ] do if [ $prosesAdedi -gt 10 ] then sleep 1 # Proses Adedi 10'u geçtiyse 1 saniye beklenir else tarama "$url" & # Paralel olarak "tarama" fonksiyonu çağırılır. break fi done done |
Betiklerde en sık kullanılan ifadeler / kontroller aşağıdaki gibi listelenebilir.
- Çalıştırılan komutun sonucu için “$?” kullanılabilir. Bu değer “0” ise komut doğru çalışmıştır. Eğer program düzgün çalışırsa 0, çalışmazsa pozitif rastgele bir değer (genellikle “1”) elde edilir.
- Fonksiyonun veya betiğin aldığı paramtere adedi $# ile elde edilebilir.
- Betiğin $0 ID’li ilk paramtresi o betiğin adıdır.
- Betiğin aldığı parametreler $1, $2, $3,… olarak elde edilebilir.
Her betiğin bir kullanım dosyası bulunmalıdır. Örnek bir kullanım dosyası aşağıdaki gibi hazırlanabilir.
1 2 3 4 5 6 |
function kullanim() { echo -e "Betiğin kullanımı hatalıdır. Doğru kullanım: \n \t $0 -d IpAdresi -r IpAgi -o CiktiDosyasi" echo "$#" adet parametre olmalıdır. Girdiğiniz parametreler: "$@" exit 1 } kullanim |
Betik içerisinde betiğe verilen parametre sayısı kontrol edilmelidir. 6 parametre bekleyen bir betikte kontrol aşağıdaki gibi gerçekleştirilebilir.
1 2 3 4 5 |
if [ ! $# -eq 6 ] then echo "6 adet parametre girilmelidir...." kullanim fi |
Betiğin parametrelerinin doğruluğu kontrol edilmelidir. Parametre olarak “-i”, “-n” ve “-o” alan bir betikte parametre kontrolü aşağıdaki gibi gerçekleştirilebilir.
1 2 3 4 5 |
if [ $1 != "-i" ] || [ $3 != "-n" ] || [ $5 != "-o" ] then echo "Parametrelerde (-i, -n, -o) hata bulunmaklıdır..." kullanim fi |
Not: Parametre teyidi sırasında if/elif/else veya case/esac kontrolleri ile hatalı parametre de ekrana bastırılabilir. Bunun yanında Getops kullanılarak sıra bağımsız kontroller de sağlanabilir.
Çalıştırılacak harici araçların mevcudiyeti kontrol edilmelidir. Örnek:
1 2 3 4 5 6 7 8 9 |
function aracinMevcudiyetKontrolu () { hydra_yolu="/usr/bin/hydra" if [ ! -f "$hydra_yolu" ] then echo "\"$hydra_yolu\" bulunamamistir..." exit 1 fi } aracinMevcudiyetKontrolu |
Çıktıların yazılacağı dosyanın başka bir dosyanın üzerine yazmaması gerekebilir. Bu sebeple çıktıların yazılacağı dosyanın mevcudiyetini kontrol etmek gerekebilir. Kontrol aşağıdaki gibi gerçekleştirilebilir.
1 2 3 4 5 6 7 8 9 |
function ciktiDosyasiKontrolu() { DOSYA=$1 if [ -f $DOSYA ]; then echo "$DOSYA adli dosya bulunmaktadir. Baska bir dosya ismi belirtiniz..." exit 1 fi } ciktiDosyasiKontrolu yeniDosya |
Bir değişkenin sadece fonksiyon içerisinde geçerli olması isteniyorsa, o değişken yerel (“local”) olarak belirtilmelidir. Aşağıdaki örnekte “sayi” değişkeni fonksiyon dışında geçersizdir.
1 2 3 |
function ornek{ local sayi=10 } |
Çalıştırılacak betikte hata kontrolü gerçekleştirme ihtiyacı olabilir. Böylece betiğin ilerleyii görülebilir ve hata tespiti kolaylaşabilir.
1 |
bash -x ./betik.sh |
Not: Derlenen diller (C, C++), yorumlayıcı dillerden (Bash, Python,…) daha hızlıdır.