Linux & Bash Script

Posted on Updated on

Bu yazıda Linux’un yapısına kabaca göz atıp, bash script ile ilgili örnekler anlatmaya çalışacağım… Linux’u sıfırdan anlatmak yerine şurada ki ve şurada ki yazıya bakmanızı önerebilirim… Az çok bilgi sahibi iseniz devam edebiliriz;

Katmanlar
Linux işletim sistemi 4 katmana ayrılabilir:

  • Donanım: CPU/RAM gibi donanımlardır.
  • Çekirdek: Kernel, sürücüler bulunur. Çalıştırılması istenen komutlara cevabı verir.
  • Kabuk: Çalıştırılması istenen komutları çalıştırır.
  • Uygulama: Kullanıcıya en yakın katmandır.

Kullanıcı uygulama ile komutu çalıştırma isteğinde bulunur. Uygulama bu isteği alır ve  kabuğa gönderir. Kabuk komutu çalıştırır ve çekirdeğe gönderir. Çekirdek bir cevap üretir ve cevabı kabuğa geri yollar. Kabuk uygulamaya, uygulama da kullanıcıya geri bildirimde bulunur.
Bilindiği gibi Linux da her şey dosyadır. En üstte bir kök(root) bulunur, belli bir hiyerarşi ile bunlar sıralanır. Eğer bir programı/paketi silmek istiyorsanız bulunduğu dosyayı silmeniz yeterli olacaktır. Windows da olduğu gibi kayıt defteri gibi benzeri yapılar barındırmaz. Windows’a program ekleyip kaldırdıkça kayıt defterinde gereksiz birçok şeyin izi kalır, bu nedenle zamanla performans azalır. Linux da durum dosya/dizin mantığı ile çözüldüğü için bu gibi sorunlar oluşmamaktadır.
Önemli dosya/dizin kavramlarına ve linux komutlarına şurada daha önce değinmiştik.

Kabuklar

Kullanıcının çalıştırdığı komutların kabuğu $SHELL değişkeninde saklanır.  csh, sh, ksh, bash bazı kabuklardır. Kabuktan çıkış yapmak için CTRL+D kullanılabilir.
Kullanıcının çalıştırdığı komutlar $PATH içerisindeki dizinlerde bulunmalıdır. Bir komut 2 farklı yerde bulunursa ilk bulunduğu yerdeki komut çalıştırılr.
shellKullanıcıların oturumunu açtığında ilk düşeceği kabuk /etc/passwd dosyasında belirtilmektedir.

Kabuk değeri “/bin/false“, “/usr/sbin/nologin” gibi bir değer ise bu kullanıcı oturum açamaz. Güvenlik açısından servislerin oturum açamaması, sadece haklarına göre komut çalıştırabilmesi gerekir. Bu sebeple kabuk değerlerinin bu şekilde olması tavsiye edilmektedir.

Kullanıcıların çevresel bilgileri “env” ile izlenebilir:
env

Örnek bir “/etc/passwd” dosyasının ilk 10 satırı aşağıdaki gibidir.
headPassw

Sistemde “root” hakkı bulunan kullanıcıların listelenmesi (id=0)
root_

“:” ile ayrılmış olarak 7 tane kolon bulunmaktadır. Bu kolon bilgileri şu şekildedir.

  • 1. kolon: Kullanıcı adı
  • 2. kolon: Kullanıcı parolası (Güvenlik sebebiyle “/etc/shadow” içerisinde saklıdır)
  • 3. kolon: Kullanıcı Id. root kullanıcısının id değeri “0”‘dır
  • 4. kolon: Grup Id
  • 5. kolon: ek bilgiler (Tam adı, Oda no, iş numarası, ev numarası, vs)
  • 6. kolon: Kullanıcının masaüstünün bulunduğu ev (home) dizini
  • 7. kolon: Komutların çalıştırılacağı dizin.

Girdi/Çıktı işlemleri

3 çeşit Girdi/Çıktı işlemi olabilir:

  • Standart Girdi (stdin): Klavyeden veri akışı beklenir. Değeri “0” ‘dır.
  • Standart Çıktı (stdout): Ekrana doğru veri akışı gönderilir. Değeri “1” ‘dir.
  • Standart Hata (stderr):  Ekrana hatalı veri akışı gönderilir.  Değeri “2” ‘dir.

Eğer hatanın ekrana basılmaması isteniyorsa sonuç “/dev/null”‘a gönderilir. Script örneklerinde bunu kullanacağız.
Yavaş yavaş bash script’e ısınmaya başlayalım…

Örnek : 3. satırdaki kullanıcı bilgilerinin harf sayısını bulma
örnek1

Örnek : En çok çalıştırılan 10 komut
sort

Burada; ‘history’ komutu ile kullandığımız tüm komutları alıyoruz. ‘awk {‘print$2′}’ komutu ile 2. sütunu alıp çıktısını sort’a atıyoruz ve sıralamayı sonraki komutlara göre yapıyor.
Betik yazma ile ilgili örneklere bakalım;


Örnek 1;

#Bu betikte 2 farklı zamandaki arp tablosunu karşılaştırıyorduk. 
#kullanım: ./arp.sh 10.17.200.1/24      (bulunduğumuz subneti yazmamız gerekiyor.)
#ip subneti nmap'te kullanmak için bir değişkene atıyoruz. ip_range=$1
#Arp komutuyla arp tablosunu bir dosyaya yazıyoruz. 
arp -na > arp1.txt
# Daha sonra "nmap ping scan" yapıyoruz. Böylece arp tablomuza yeni ip'ler eklenmiş oluyor. 
nmap -n -sn $ip_range >/dev/null
#Tekrar arp'la çıktı alıp bir dosyaya yazıyoruz. 
arp -na > arp2.txt
# Dosyaları karşılaştırıyoruz ve  sonucu bir dosyaya yazıyoruz. 
diff arp1.txt arp2.txt > difference.txt

Örnek 2;

#Bu betik /tmp dizininde yeni bir isimle bir dosya oluşturuyor.
#Burada önemli olan var olan bir dosyanın üzerine yazmamak. 
#Bu nedenle oluşturduğumuz isimde bir dosya var mı diye denetlememiz gerekiyor.
#Betik herhangi bir girdi gerektirmiyor. /tmp klasörü altında yeni bir dosya oluşturuyor.
#Bunu random_dosya diye bir fonksiyon tanımlayarak yaptık. Ve bu fonksiyonu çalıştırdık. 
function random_dosya() {
#RANDOM her çalıştırıldığında 5 basamaklı farklı bir değer üretiyor. Burada rastgele bir dosya ismi üretip 
#"name" değişkenine atıyoruz. 
name="`echo sge_$RANDOM.txt`"
#sonsuz döngü çalıştırıyoruz. Buradan sadece break komutuyla çıkılabiliyor. 
while [ 1 ] 
do 
#/tmp dizinindeki dosyaları listeliyoruz ve oluşturduğumuz dosya ismi için "grep" komutunu çalıştırıyoruz.  
     ls /tmp | grep -q "$name" 
#Eğer dosya ismi listesi varsa başarı sonucu($?) 0 dönecektir, başarısızsa 0'dan farklı bir sonuç dönecektir.  
     if [ $? -eq 0 ]  then 
#Eğer başarılıysa, yani dosya ismi varsa, yenibir değişken oluşturup. While komutunun başına dönüyoruz.         
          name="`echo sge_$RANDOM.txt`"        
     else 
#Eğer başarısızsa, yani dosya bulunmuyorsa, dosyanın dizin ismiyle bir dizin  tanımlatıp bu değişkenle 
#"touch" komutunu kullanıp yeni dosyayı oluşturuyoruz.Ve break komutuyla while içerisinden çıkıyoruz.         
          new_name="/tmp/$name"         
          touch  $new_name         
          break  
     fi 
done 
}
 .#Burada yukarıda tanımlanmış fonksiyonu çalıştırıyoruz. 
random_dosya

Örnek 3;

#Bu betikte işletim sistemi üzerinde (localhost üzerinde çalışanlar hariç) 
#çalışan tcp servislerini ve servis numaralarını yazmamız gerekiyordu. 
#Burada iki yolla yaptım. İlkini yorum şekline dönüştürdüm. 
#çıktı "631 -> portmap" gibi olması gerekiyor.
#1.Yol:Önce netstat çalıştırıyoruz. Daha sonra tcp ile başlayan satırları 
#grep'liyoruz,sonra "127.0.0.1" geçen satırları çıkarıyoruz. 
#Daha sonra "PID/Program name" #kolonunu (7. kolon) yazdırıyoruz. çıktı 
#"631/portmap" #şeklinde oluyor. Bunu da son #awk komutuyla "/" ayaç 
#olarak kullanarak istenilen şekilde yazdırıyoruz.
#-->  netstat -nlput |grep -E "^tcp " |grep -v "127.0.0.1"| awk 
#'{print $7}' | awk  -F "/" '{ print $1, "->", $2}'
#2.Yol: Burada en sonki awk komutu yerine cut kullanıyoruz. 
netstat -nlput |grep -E "^tcp " |grep -v "127.0.0.1"| awk '{print $7}' |while read -r line 
do 
     pr_id="` echo $line |cut -d "/" -f 1 `" 
     pr_name="`echo $line | cut -d "/" -f 2 `"
echo "$pr_id -> $pr_name"  
done

Örnek 4:

# Bu betikte ping komutunu kullanarak bulunduğumuz subnetteki açık 
#bilgisayarları(ping'e cevap dönen)bulmaya çalışıyoruz. 
#Ben ilkönce kendi ip'mi betiğe girdi olarak vererek subnette olabilecek 
#bütük ip numaralarını ürettim. 
#Daha sonra bu ip'lere sırayla ping atarak "ttl" kelimesi içeren ipleri 
#"up" olarak belirledim. Değilse "down" olarak belirledim.   
#!/usr/bin/env bash #girdi olarak kendi ip adresinizi vermeniz gerekiyor. 
echo "kullanim : $0 ip_adresi"
#full subnet listesinin hazirlanmasi #kendi ip adresimin ilk 3 oktetini alıp son oktete 1'den 254'e kadarki sayıları yazdırıyorum. 
#Örnek: 192.168.1.45 için 192.168.1."değişken" 
#-------------------------------------------------- 
rm -rf ip_list.txt  #eskiden oluşturulmuşsa silmek için... 
my_ip=$1 subnet_ip="`echo $my_ip | cut -d "." -f 1,2,3 `" 
host_ip=1
for host_ip in `seq 1 254` 
do
      echo "$subnet_ip.$host_ip" >> ip_list.txt 
done
#-------------------------------------------------- 
# ip_list.txt içindeki iplere ping atilip yanitin incelenmesi
for ip_num in $( cat /root/Desktop/ip_list.txt ) 
do
     ping $ip_num -c 1   |grep ttl   #her ip adresine 1 kere ping atıyorum. Ve grep'liyorum.
     if [ $? -eq 0 ]  
          then   
     echo "Host $ip_num is up "  
          else   
     echo "Host $ip_num is down"  
     fi 
done
#--------------------------------------------------

Örnek 5;

#Bu betikteki amacımız nmap'in ping servisini kullanarak ağdaki açık bilgisayarları bulmak 
#Ben kendi ip adresimi girdi olarak vererek bulunduğum subnette nmap null-scan çalıştırdım. 
#Ve sonuçlardan  ip adreslerini grep'ledim.
#!/usr/bin/env bash
echo "kullanim : $0 ip_adresi"
ip_adresi=$1 
echo "Agdaki IP Adres Listesi:" 
nmap -n -sn $ip_adresi/24 | grep -E "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" | cut -d " " -f 5

Örnek 6;

# Bu betikteki amacımız 80. portu açık olan ip adreslerini firefox'ta yeni bir tabda çalıştırmak.
#!/usr/bin/env bash #subnetimizi girdi olarak betiğe veriyoruz. Örnek: ./port.sh 192.168.1.1/24 
ip_range=$1 
# Önce Nmap'le 80. portu açık olan ip adreslerini bir dosyaya yazıyoruz. 
nmap -n -p 80  --open $ip_range -oA cikti >/dev/null 
#çıktıdan ip adreslerini çekip yeni bir dosyaya yazıyoruz. 
cat cikti.nmap | grep -v "#" | grep -E "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$" |cut -d " " -f 5 > ip_list.txt 
#Dosyadaki ip adreslerini firefox'a girdi olarak vererek yeni bir sekmede açıyoruz. 
for ip_num in $( cat ip_list.txt ) 
do  
     firefox -new-tab  $ip_num & 
done

Örnek 7;

#!/bin/bash
#Bu betik; 2 saniyede bir deneme.txt dosyasına toplam ram,kullanılan 
#ve aktif ram bilgisini yazıyor
while (true)
do
    memtotal=`cat /proc/meminfo | head -1 | awk '{print $2}' `
    buffers=`cat /proc/meminfo | head -3 | tail -1 | awk ' {print $2}' `
    active=`cat /proc/meminfo | head -6 | tail -1 | awk ' {print $2}' `echo "$memtotal,$buffers,$active" >> deneme.txt
sleep 2
done

#Bu betik önceden oluştuduğumuz deneme.txt dosyasından aldığı bilgileri okuyor;
#Sistemde kullanılan;toplam ram,kullanılan ve aktif ram bilgisini
#Tablo halinde oluşturulan deneme.html dosyasına yazdiriyor
> deneme.html
echo '<head>Baslik Buraya<html/><body><table border="2" bordercolor="black"><tr>' >> deneme.html
echo "<td> Toplam Ram </td>" >> deneme.html
echo "<td> Kullanilan </td>" >> deneme.html
echo "<td> Aktif kullanilan </td></tr>" >> deneme.html
cat deneme.txt | while read line
do 
     toplam=`echo $line | cut -d, -f1`
     kullanilan=`echo $line | cut -d, -f2`
     aktif=`echo $line | cut -d, -f3`
echo "<tr><td>$toplam</td><td>$kullanilan</td><td>$aktif</td></tr>" >> deneme.html
echo "<tr><td>$toplam</td><td>$kullanilan</td><td>$aktif</td></tr>" 
done
echo "</table></body>" >> deneme.html

Örnek 8;

#!/bin/bash0
#Bu betik; saat ??:05 (Her saati 5 geçe)'de bir önceki saatten o anki saate kadar olan 
#sistem log mesajlarının sayısını deneme2.html dosyasına basıyor
 > /root/Desktop/deneme2.html
l=$((`date "+%m"`-1))
sayi=`cat /var/log/messages | grep "$i" | wc -l`
if [ `date "+%m"` -ne 00 ]
then
     i=`date "+%b 0$l %y"`
else
     i=`date "+%b 24 %y"`
fi
echo "`date`,$sayi" >> /root/Desktop/deneme2.txt 
echo '<html><body><table border="2" bordercolor="black"><tr>' >> /root/Desktop/deneme2.html
echo "<td> sistem zamani </td>" >> /root/Desktop/deneme2.html
echo "<td> sayi </td></tr>" >> /root/Desktop/deneme2.html
cat /root/Desktop/deneme2.txt | while read line
do
     sat1=`echo $line | cut -d, -f1`
     sat2=`echo $line | cut -d, -f2`
     echo "$sat1"
     echo "$sat2"
     echo "<tr><td>$sat1</td><td>$sat2</td></tr>" >> /root/Desktop/deneme2.html
done 
echo "</table></body></html>" >> /root/Desktop/deneme2.html
firefox /root/Desktop/deneme2.html
#Bu betiği otomatik olarak çalıştırmak için; 
# crontab -e
# */5 * * * * /root/Desktop/betikAdi
#kaydet ve çık (ctrl+x ile kaydet)
#Yaptığımız değişikliği listelemek için; 'crontab -l' komutu çalıştırılır(Firefox'da crontab'ın değişikliğini görmek için manuel olarak refresh yapılmalı)

Zamanla yeni örnekler eklenecektir…
Yazıyı yazmamda katkısı bulunan; G.Alkan, M.E.Akçelik, H.H.Özbenli ve V.Hataş’a teşekkür ederim…

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s