Kabuk
Transkript
Kabuk
İşletim Sistemleri İşletim Sistemleri Dr. Binnur Kurt [email protected] Omega Eğitim ve Danışmanlık http://www.omegaegitim.com Bölüm 2 Kabuk 1|Sayfa İşletim Sistemleri İÇİNDEKİLER 1. İşletim Sistemi 2. Kabuk 3. Prosesler 4. İplikler 5. İplikler Arası Eş Zamanlama 6. Prosesler Arası İletişim 7. İş Sıralama 8. Prosesler Arası Eş zamanlama 9. Bellek Yönetimi 10. Dosya Sistemi 11. Soket Haberleşme Bölüm 2 Kabuk 2|Sayfa İşletim Sistemleri BÖLÜM 2 Kabuk Bölümün Amacı Bölüm sonunda aşağıdaki konular öğrenilmiş olacaktır: ► Kabuğun özellikleri ve işletim sistemindeki görevleri ► Kabuk komut formatı ► Kabuk programlama o Değişkenler o Aritmetik İşlemler o Koşullar ve Döngüler o Fonksiyonlar Bölüm 2 Kabuk 3|Sayfa İşletim Sistemleri 2.1 Kabuk nedir? İşletim sistemlerinde, çekirdek sistem kaynaklarını yönetmekten sorumludur. Bunun için çok sayıda servisten oluşur. Bu servisler genel olarak prosesler arasında işlemci ve bellek gibi kaynaklara erişimini düzenler. Servislere sistem çağrıları ile ulaşılır. İşletim sistemi ile kullanıcı programları arasında tanımlanmış bir arayüz vardır. Bu arayüz bir dizi yordamdan oluşur. Bu yordamların neler olduğu, aldıkları parametreler ve parametre tipleri IEEE POSIX standardı tarafından tanımlanmıştır. Bu yordamlara ulaşmak için trap işletimci komutundan yararlanılır. trap kesmesi ile birlikte kontrol ilgili yordama geçer ve kod çekirdek seviyesinde koşmaya başlar. Ancak sistem çağrıları alt düzey çağrılar olduğu için, sistem yönetimi ile ilgili işler için sistem çağrılarını kullanmak zordur. Bunun için sistem komutlarını kullanıyoruz. Örneğin dosya kopyalamak için cp komutu kullanılır. Kabuk kullanıcı için bir komut satırı sağlar ve buradan kullanıcının girdiği komutları çalıştırır ve sonucu listeler. Kabuğun görevleri aşağıdaki gibi sıralanabilir: a. Çekirdek ile kullanıcı arasında bir arayüz tanımlar. b. Komut satırı yorumlayıcısıdır. Kullanıcıdan aldığı komutları çekirdeğin anlayacağı sistem çağrılarına dönüştürür. c. Programlama ortamı sağlar. Böylelikle karmaşık komutlar ya da periyodik olarak çalıştırılacak işler bir betik haline getirilebilir. Bu betikler ilgili kabuk tarafından çalıştırılır. 2.2 Kabuk Türleri Tarihsel olarak Unix işletim sistemi geliştirilirken çok sayıda kabuk yazıldığını görüyoruz. Bunlar arasında çok sık karşılaştığımız kabukların listesini aşağıda veriyorum: Bourne Shell sh Korn Shell ksh C Shell csh TC Shell tcsh B(ourne)A(gain) Shell bash Desktop Korn Shell dtksh Job Control Shell jsh Restricted Shell rsh Z Shell zsh Bu kabuklar arasında hız, güvenlik seviyesi, programlama yetenekleri gibi farklılıklar bulunur. Bu kabuklardan sıkça kullanılan birkaç tanesine bir göz atalım. 2.2.1 Bourne Shell (sh) AT&T Bell laboratuvarında Steve R. Bourne tarafından yazılmıştır. Kabuk betiklerinde en çok tercih edilen kabuktur. Bourne kabuğu, hız ve taşınabilirliği ile öne çıkmaktadır. Solaris işletim sisteminde varsayılan kabuk sh’dır. Ancak bazı önemli eksikleri bulunmaktadır: eski komutları hatırlamaz, aritmetik ve mantıksal işleçler Bölüm 2 Kabuk 4|Sayfa İşletim Sistemleri bulunmaz. root kullanıcısı için varsayılan imleç # ve diğer kullanıcılar için ise imleç $ sembolleridir. Solaris işletim sisteminde açılış betikleri Bourne kabuğu tarafından çalıştırılır. 2.2.2 C Shell (csh) California Üniversitesinde, Bill Joy tarafından yazılmıştır. Önceki komutları hatırlaması, aritmetik ve C benzeri ifadeler yazılabilmesi ve takma isim tanımlanabilmesi en önemli özellikleridir. Ancak Bourne kabuğundan daha yavaştır. root kullanıcısı için varsayılan imleç # ve diğer kullanıcılar için ise imleç % sembolleridir. 2.2.3 Korn Shell (ksh) AT&T Bell laboratuvarında David Korn tarafından yazılmıştır. Bourne kabuğunu kapsar. Bu nedenle Bourne kabuğu için yazılan betikler Korn kabuğunda da çalışabilir. C kabuğu ile benzer özelliklere sahiptir. Önceki komutları hatırlar, aritmetik ve mantıksal işlemleri destekler, dizi ve fonksiyon tanımlanabilir. C kabuğundan daha hızlıdır. root kullanıcısı için varsayılan imleç # ve diğer kullanıcılar için ise imleç $ sembolleridir. GNU/Linux işletim sisteminde varsayılan kabuk BASH’dir. 2.3 Komut Formatı Kabuk kullanıcıdan aldığı komutları çalıştırır. Bu komutların belirli bir formatı vardır. Komutlar – ile verilen seçenek ile parametre değerlerini alırlar. Komutların düzgün kullanımı için seçeneklerin ve parametrelerin neler olduğunun bilinmesi gerekir. Bunun için öncelikli olarak man komutuna başvurulabilir: [[email protected] ~]$ man cal Bölüm 2 Kabuk 5|Sayfa İşletim Sistemleri Bir komutu eğer izin veriyorsa birden fazla seçenekle ya da seçeneksiz olarak çalıştırabiliriz: [[email protected] ~]$ uname Linux [[email protected] ~]$ uname -a Linux server1.example.com 3.8.13-16.2.1.el6uek.x86_64 #1 SMP Thu Nov 7 17:01:44 PST 2013 x86_64 x86_64 x86_64 GNU/Linux [[email protected] ~]$ uname -i x86_64 [[email protected] ~]$ uname -r 3.8.13-16.2.1.el6uek.x86_64 [[email protected] ~]$ uname -s Linux [[email protected] ~]$ uname -r -s Linux 3.8.13-16.2.1.el6uek.x86_64 [[email protected] ~]$ uname -s -r Linux 3.8.13-16.2.1.el6uek.x86_64 [[email protected] ~]$ uname -rs Linux 3.8.13-16.2.1.el6uek.x86_64 [[email protected] ~]$ uname -sr Linux 3.8.13-16.2.1.el6uek.x86_64 [[email protected] ~]$ uname -rs -i Linux 3.8.13-16.2.1.el6uek.x86_64 x86_64 [[email protected] ~]$ uname -rsi Linux 3.8.13-16.2.1.el6uek.x86_64 x86_64 [[email protected] ~]$ uname -r -s -i Linux 3.8.13-16.2.1.el6uek.x86_64 x86_64 Yukarıda uname komutunu herhangi bir seçenek vermeden çalıştırdık. Birden fazla seçenek vererek çalıştırdık. Birden fazla seçenek alması durumunda bu seçenekleri toplu olarak verebileceğimiz gibi ayrı ayrı da verebiliriz: -sir ile -s –i -r aynı anlama gelir. Benzer şekilde –si -r ile -s –i -r aynı anlama gelir. Bazen komutlar parametre alabilirler. Cal komutu ekrana takvimi döker. Eğer bir parametre verilmemiş ise içinde bulunulan yılın ve ayın takvimini ekrana döker. İstenirse ay ve yıl parametreleri verilebilir: [[email protected] ~]$ cal September 2014 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 [[email protected] ~]$ cal 7 1973 July 1973 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 Bölüm 2 Kabuk 6|Sayfa İşletim Sistemleri 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 İstenirse sadece yıl parametre olarak verilerek o yılın takvimi ekrana dökülebilir: [[email protected] ~]$ cal 1973 1973 Su Mo 1 7 8 14 15 21 22 28 29 January Tu We Th 2 3 4 9 10 11 16 17 18 23 24 25 30 31 April Tu We Th 3 4 5 10 11 12 17 18 19 24 25 26 Fr 5 12 19 26 Sa 6 13 20 27 Fr 6 13 20 27 Sa 7 14 21 28 Su 1 8 15 22 29 Mo 2 9 16 23 30 Su 1 8 15 22 29 Mo 2 9 16 23 30 July Tu We Th 3 4 5 10 11 12 17 18 19 24 25 26 31 Fr 6 13 20 27 Sa 7 14 21 28 Su Mo 1 7 8 14 15 21 22 28 29 October Tu We Th 2 3 4 9 10 11 16 17 18 23 24 25 30 31 Fr 5 12 19 26 Sa 6 13 20 27 February Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 Su Mo Tu 1 6 7 8 13 14 15 20 21 22 27 28 29 May We Th 2 3 9 10 16 17 23 24 30 31 Fr 4 11 18 25 Sa 5 12 19 26 August Su Mo Tu We Th 1 2 5 6 7 8 9 12 13 14 15 16 19 20 21 22 23 26 27 28 29 30 Fr 3 10 17 24 31 Sa 4 11 18 25 November Su Mo Tu We Th 1 4 5 6 7 8 11 12 13 14 15 18 19 20 21 22 25 26 27 28 29 Fr 2 9 16 23 30 Sa 3 10 17 24 March Su Mo Tu We Th 1 4 5 6 7 8 11 12 13 14 15 18 19 20 21 22 25 26 27 28 29 Fr 2 9 16 23 30 Sa 3 10 17 24 31 June Su Mo Tu We Th Fr 1 3 4 5 6 7 8 10 11 12 13 14 15 17 18 19 20 21 22 24 25 26 27 28 29 Sa 2 9 16 23 30 September Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 December Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 Yukarıdaki örneklerden de anlaşılacağı gibi komutların kaç parametre alabildikleri ve parametrelerin sırasının bir önemi bulunmaktadır. Bu sıralamanın ne olduğunu öğrenmek için man komutu ile kullanım kılavuzunu (=Manual Page) okumak gerekir. Bazen komutlar hem seçenek hem de parametre verilerek çalıştırılır: [[email protected] /]$ ls bin boot cgroup dev etc home lib lib64 lost+found media misc mnt net opt oradata proc root sbin selinux srv sys tmp usr var [[email protected] /]$ ls -l total 106 dr-xr-xr-x. 2 root root dr-xr-xr-x. 5 root root drwxr-xr-x. 10 root root drwxr-xr-x. 20 root root drwxr-xr-x. 125 root root drwxr-xr-x. 5 root root drwxr-xr-x. 11 root root dr-xr-xr-x. 10 root root drwx------. 2 root root drwxr-xr-x. 3 root root Bölüm 2 Kabuk 4096 1024 4096 4260 12288 4096 4096 12288 16384 4096 Apr Apr Apr Sep Sep Apr Nov Apr Apr Sep 30 29 29 22 22 30 8 30 29 22 03:49 11:31 11:38 00:34 00:38 02:22 2013 03:49 11:09 00:35 bin boot cgroup dev etc home lib lib64 lost+found media 7|Sayfa İşletim Sistemleri drwxr-xr-x. 2 root drwxr-xr-x. 4 root drwxr-xr-x. 2 root drwxr-xr-x. 15 root drwxr-xr-x. 3 oracle dr-xr-xr-x. 180 root dr-xr-x---. 38 root dr-xr-xr-x. 2 root drwxr-xr-x. 7 root drwxr-xr-x. 2 root dr-xr-xr-x. 13 root drwxrwxrwt. 20 root drwxr-xr-x. 15 root drwxr-xr-x. 22 root root 0 Sep 16 18:44 misc root 4096 Apr 30 06:02 mnt root 0 Sep 16 18:44 net root 4096 May 12 01:26 opt oracle 4096 Apr 30 03:37 oradata root 0 Sep 16 18:44 proc root 4096 Sep 22 01:34 root root 12288 May 6 09:35 sbin root 0 Sep 16 18:44 selinux root 4096 Nov 1 2011 srv root 0 Sep 16 18:44 sys root 4096 Sep 22 01:50 tmp root 4096 May 11 20:58 usr root 4096 Apr 29 11:28 var [[email protected] /]$ ls -l /var total 80 drwxr-xr-x. 2 root root 4096 Apr drwxr-xr-x. 17 root root 4096 Apr drwxr-xr-x. 2 root root 4096 Nov drwxr-xr-x. 2 root root 4096 Oct drwxr-xr-x. 3 root root 4096 Apr drwxr-xr-x. 3 root root 4096 Apr drwxr-xr-x. 2 root root 4096 Nov drwxrwx--T. 2 root gdm 4096 Nov drwxr-xr-x. 46 root root 4096 Apr drwxr-xr-x. 2 root root 4096 Nov drwxrwxr-x. 6 root lock 4096 Sep drwxr-xr-x. 14 root root 4096 Sep lrwxrwxrwx. 1 root root 10 Apr drwxr-xr-x. 2 root root 4096 Nov drwxr-xr-x. 2 root root 4096 Nov drwxr-xr-x. 2 root root 4096 Nov drwxr-xr-x. 32 root root 4096 Sep drwxr-xr-x. 14 root root 4096 Apr drwxrwxrwt. 3 root root 4096 Sep drwxr-xr-x. 6 root root 4096 Apr drwxr-xr-x. 3 root root 4096 Apr 29 29 18 11 29 29 1 22 30 1 21 21 29 1 1 1 21 29 11 29 29 11:28 11:38 2013 2013 11:28 11:25 2011 2013 02:17 2011 21:11 21:11 11:10 2011 2011 2011 20:38 11:22 10:52 11:21 11:21 account cache crash cvs db empty games gdm lib local lock log mail -> spool/mail nis opt preserve run spool tmp www yp Bazen uzun soluklu bir komutu çalıştırdığımızda, tamamlanmasını beklemeden sonlandırmak isteriz. Bu durumda Ctrl+C tuşlarına basmamız yeterli olur: [[email protected] /]$ sleep 10 (10 saniye sonra) [[email protected] /]$ sleep 10 ^C Kabuk her seferinde tek bir komut çalıştırır. Bazen birden fazla komutu tek bir seferde verip, çalıştırılmasını isteriz. Bu durumda birden fazla komutu, komutlar arasına ; sembolü koyarak giriyoruz: [[email protected] /]$ cal 7 1973 ; date ; uname -rs July 1973 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 Bölüm 2 Kabuk 8|Sayfa İşletim Sistemleri 22 23 24 25 26 27 28 29 30 31 Mon Sep 22 01:58:19 EEST 2014 Linux 3.8.13-16.2.1.el6uek.x86_64 2.4 Alt Kabuk Her kullanıcı için bir varsayılan kabuk vardır. Bunu echo $SHELL komutu ile öğrenebiliriz: [[email protected] ~]$ echo $SHELL /bin/bash Bu örnekte varsayılan kabuğun Bash olduğunu anlıyoruz. Şu an kullanmakta olduğumuz kabuğu anlamak için ps komutunu çalıştırmamız yeterli olur: [[email protected] ~]$ ps PID TTY TIME CMD 3819 pts/0 00:00:00 bash 3843 pts/0 00:00:00 ps ps komutu açtığımız terminalde çalışan uygulamaların listesini verir. Tüm çalışan uygulamaların yani proseslerin listesini almak için ps -fe komutunu kullanıyoruz: Bu örnekte Bash kabuğu ile konuştuğumuzu anlıyoruz. (Şekil-2.1) Bölüm 2 Kabuk 9|Sayfa İşletim Sistemleri Şekil-2.1 Bash kabuğunun çalıştığı terminal penceresi Bir kabuktan diğerine geçiş yapmak mümkündür. Bunun için basitçe geçiş yapmak istediğimiz kabuğun komutunu çalıştırmak yeterli olur. Geçiş yaptığımız kabuğa alt kabuk adını veriyoruz. Şimdi önce Korn kabuğuna ardından C kabuğuna geçiş yapalım: [[email protected] ~]$ ksh $ ps PID TTY TIME CMD 3819 pts/0 00:00:00 bash 5746 pts/0 00:00:00 ksh 5747 pts/0 00:00:00 ps $ csh [[email protected] ~]$ ps PID TTY TIME CMD 3819 pts/0 00:00:00 bash 5746 pts/0 00:00:00 ksh 5749 pts/0 00:00:00 csh 5757 pts/0 00:00:00 ps Oluşan yapıyı Şekil-2.2’den izleyebilirsiniz. Tekrar üst kabuğa geri dönmek için ise exit komutu çalıştırılır: [[email protected] ~]$ exit $ ps PID TTY TIME CMD 3819 pts/0 00:00:00 bash 5746 pts/0 00:00:00 ksh 5801 pts/0 00:00:00 ps $ exit [[email protected] ~]$ ps PID TTY TIME CMD 3819 pts/0 00:00:00 bash 5802 pts/0 00:00:00 ps Bölüm 2 Kabuk 10 | S a y f a İşletim Sistemleri bash exit ksh ksh exit csh csh Şekil-2.2 Alt kabuklar arası geçişler 2.5 Kabuk Değişkenleri Alt kabuk kavramı özellikle çevre değişkenleri ile çalışırken önemlidir. İki tür çevre değişkeni bulunur: Yerel ve Global. Çevre değişkeni tanımlamak son derece kolaydır: [[email protected] ~]$ VAR1=deneme [[email protected] ~]$ echo $VAR1 deneme Burada VAR1 değişkeni yerel bir değişkendir. Değişkenlerin değerlerini echo komutu ile öğrenebiliriz. echo komutu ile değişkeni adreslerken değişkeninin adının önüne $ sembolü koyuyoruz. Yerel değişken olduğu için bir alt kabukta çalışmaya başladığımızda değerine erişemiyoruz: [[email protected] ~]$ ksh $ echo $VAR1 $ exit [[email protected] ~]$ echo $VAR1 deneme Değişkeni global yapmak için ise export komutunu kullanıyoruz: [[email protected] ~]$ export VAR1=deneme [[email protected] ~]$ echo $VAR1 deneme [[email protected] ~]$ ksh $ echo $VAR1 deneme $ exit [[email protected] ~]$ echo $VAR1 deneme Şimdi VAR1 değişkeni global bir değişkene dönüştüğünden Korn kabuğundan değerine ulaşabildik. Bölüm 2 Kabuk 11 | S a y f a İşletim Sistemleri Yerel ve global değişkenler arasındaki farkı gösteren başka bir örneği aşağıda bulabilirsiniz. Bu örnek x değişkeninin yerel değişken olarak, name değişkeninin ise export komutu ile global değişken olarak tanımlandığına dikkat ediniz: [[email protected] ~]$ x=108 [[email protected] ~]$ name="John Locke" [[email protected] ~]$ echo $name $x John Locke 108 [[email protected] ~]$ export name [[email protected] ~]$ ksh $ print $x $ print $name John Locke $ exit [[email protected] ~]$ Korn alt kabuğunda name değişkenine erişebilirken x değişkenine erişemedik. export komutunun kullanımına ilişkin diğer detayları aşağıdaki örneği inceleyerek öğreneceğiz: [[email protected] ~]$ var=value [[email protected] ~]$ export var [[email protected] ~]$ var=value ; export var [[email protected] ~]$ export var=value [[email protected] ~]$ export x=108 y=549 z=4629 [[email protected] ~]$ echo $x 108 [[email protected] ~]$ echo $y 549 [[email protected] ~]$ echo $z 4629 ; ile birden fazla komutu tek bir seferde kabuğa geçirmemiz mümkündür: var=value ; export var Burada yapılan işlem export var=value ile yapılan işlemle aynıdır. export komutu ile bir kerede birden fazla değişken tanımlanabilir. Kabuk değişkenlerine erişmek için daha yetenekli olan ${} gösterimi de kullanılmaktadır: [[email protected] ~]$ counter=1 [[email protected] ~]$ echo $counter 1 [[email protected] ~]$ echo ${counter} 1 ${} gösteriminin başka yetenekleri de vardır. Bu yetenekleri aşağıdaki örneklerde görmeye çalışalım: [[email protected] ~]$ var=x [[email protected] ~]$ echo ${var:-y} x [[email protected] ~]$ var= [[email protected] ~]$ echo ${var:-y} y [[email protected] ~]$ unset var [[email protected] ~]$ echo ${var:=y} Bölüm 2 Kabuk 12 | S a y f a İşletim Sistemleri y [[email protected] ~]$ echo ${var:=z} y [[email protected] ~]$ echo $var y Burada ${var:-y} ile var değişkenin değeri yoksa y değerini kullanması isteniyor. Burada değişkenin değerinin değişmediğine dikkat edin. Eğer değişkeninin değerinin değişmesini istiyorsanız ${var:=y} gösterimini kullanmalısınız. Değişkenin değeri üzerinde + sembolü kullanılarak bitiştirme işlemi yapılabilir: [[email protected] ~]$ for f in 4 8 15 16 23 42 > do > list=${list:+$list,}$f > done [[email protected] ~]$ echo $list 4,8,15,16,23,42 Değişken çift tırnak içinde kullanıldığında değişkeninin içeriğindeki görünmeyen karakterler ekrana basılır: [[email protected] ~]$ list="a b c d e f" [[email protected] ~]$ echo $list a b c d e f [[email protected] ~]$ echo "$list" a b c d e f 2.6 Kabuk Betikleri Çok sık çalıştırdığımız kalabalık seçenekleri olan ya da karmaşık komutları betik dosyası oluşturarak komut satırından kolayca erişilebilir hale getirebiliriz. Bunun dışında periyodik olarak çalıştırılacak işlerimiz varsa, yine bu işleri, betik dosyası oluşturup örneğin crontab servisini kullanarak otomatik olarak çalıştırabiliriz. Benzer şekilde basit karmaşıklıktaki sistem seviyesindeki problemler için betik yazmayı tercih ederiz. Daha karmaşık problemler için Perl, Python gibi daha üst düzey dilleri kullanmayı tercih ederiz. Betik dosyaları oluşturulurken belirli bir kabuk tercih edilir ve çalıştırmasını istediğimiz kabuğu ilk satırda belirtiriz: #!/bin/sh set -- * files=$# set -- */ dirs=$# echo “Dosya sayisi ($PWD): $files” echo “Katalog sayisi ($PWD): $dirs” Yukarıdaki betiği first.sh dosyasında oluşturmuş olalım. Bu betiği çalıştırabilmek için çalışma yetkisi vermemiz gerekir: [[email protected] ~]$ chmod +x first.sh Artık çalıştırabiliriz: [[email protected] ~]$ ./first.sh Dosya sayisi (/home/student): 19 Bölüm 2 Kabuk 13 | S a y f a İşletim Sistemleri Katalog sayisi(/home/student): 16 Betiği çalıştırmanın başka yolları da bulunmaktadır: a. . komutu ile çalıştırmak [[email protected] ~]$ . ./first.sh Dosya sayisi (/home/student): 19 Katalog sayisi(/home/student): 16 b. source komutu ile çalıştırmak [[email protected] ~]$ source ./first.sh Dosya sayisi (/home/student): 19 Katalog sayisi(/home/student): 16 c. betik dosyasının adını vererek çalıştırmak [[email protected] ~]$ ./first.sh Dosya sayisi (/home/student): 19 Katalog sayisi(/home/student): 16 d. Kabuk komutu ile çalıştırmak [[email protected] ~]$ sh ./first.sh Dosya sayisi (/home/student): 19 Katalog sayisi(/home/student): 16 a, b ve d’de verilen yöntemlerde betik dosyasının çalışma izninin olmasına bakılmaz. a ve b yöntemlerinde betik mevcut kabuk tarafından çalıştırılır, ayrı bir proses yaratılmaz. c ve d’de ise alt kabuk yaratılır ve betik bu alt kabuk tarafından çalıştırılır. Bu yüzden betik içinde tanımlana değişkenler export komutu ile tanımlanmış olsa bile, betik çalıştırılıp, kabuğa dönüldüğünde değişkene erişilemez: [[email protected] ~]$ echo $VAR1 [[email protected] [[email protected] deneme [[email protected] [[email protected] ~]$ . ./second.sh ~]$ echo $VAR1 [[email protected] [[email protected] deneme [[email protected] [[email protected] ~]$ source ./second.sh ~]$ echo $VAR1 ~]$ unset VAR1 ~]$ echo $VAR1 ~]$ unset VAR1 ~]$ echo $VAR1 [[email protected] ~]$ ./second.sh [[email protected] ~]$ echo $VAR1 [[email protected] ~]$ sh ./second.sh [[email protected] ~]$ echo $VAR1 [[email protected] ~]$ second.sh betiğinin içeriği aşağıdaki gibidir: #!/bin/sh export VAR1=deneme Bölüm 2 Kabuk 14 | S a y f a İşletim Sistemleri 2.7 Özel Kabuk Değişkenleri Kabukla çalışırken kullanabileceğimiz özel değişkenler vardır. Şimdi bu değişkenlere bir göz atalım: $$ Çalışan prosesin proses kimlik numarasını verir [[email protected] ~]$ cat third.sh #!/bin/sh echo $$ [[email protected] ~]$ ps PID TTY TIME CMD 3819 pts/0 00:00:00 bash 9876 pts/0 00:00:00 ps [[email protected] ~]$ echo $$ 3819 [[email protected] ~]$ ./third.sh 9879 [[email protected] ~]$ . ./third.sh 3819 [[email protected] ~]$ source ./third.sh 3819 [[email protected] ~]$ sh ./third.sh 9888 $? Son çalıştırılan prosesin exit değerini verir. Eğer sıfırsa işlem başarılı olmuştur. Sıfır dışındaki tüm değerler bir problemi işaret eder. Betiklerde hatalı durumları yakalamak için kullanılır. [[email protected] ~]$ ls /nodir ls: cannot access /nodir: No such file or directory [[email protected] ~]$ echo $? 2 [[email protected] ~]$ ls / bin dev lib media net proc selinux tmp boot etc lib64 misc opt root srv usr cgroup home lost+found mnt oradata sbin sys var [[email protected] ~]$ echo $? 0 [[email protected] ~]$ true ; echo $? 0 [[email protected] ~]$ false ; echo $? 1 $! Arka planda çalıştırılan prosesin kimlik numarasını öğrenmek için kullanılır. Aşağıdaki betik arka planda bir hesap makinası açar ve 10 saniye sonra bu hesap makinasını kapatır: Bölüm 2 Kabuk 15 | S a y f a İşletim Sistemleri #!/bin/sh gcalctool & while true ; do pid=$! sleep 10 kill -9 $pid break done & # Değişkenin içeriğinin karakter uzunluğunu verir. [[email protected] ~]$ export var="Hello Mars" [[email protected] ~]$ echo ${#var} 10 % Değişkenin içeriğinden sağdan ilk eşleşmeyi siler. %% Değişkenin içeriğinden sağdan ilk eşleşmeyi siler. # Değişkenin içeriğinden soldan ilk eşleşmeyi siler. ## Değişkenin içeriğinden soldan ilk eşleşmeyi siler. [[email protected] ~]$ var=/usr/local/bin/example [[email protected] ~]$ echo ${var%/*} /usr/local/bin [[email protected] ~]$ var=usr/local/bin/example [[email protected] ~]$ echo ${var%%/*} usr [[email protected] ~]$ var=usr/local/bin/example [[email protected] ~]$ echo ${var#*/} local/bin/example [[email protected] ~]$ var=usr/local/bin/example [[email protected] ~]$ echo ${var##*/} Example [[email protected] ~]$ export var=abcdef [[email protected] ~]$ echo ${var%${var#?}} a [[email protected] ~]$ echo ${var#${var%?}} f ${var//PATTERN/STRING} var değişkenindeki tüm PATTERN’leri STRING ile değiştirir. [[email protected] ~]$ echo -e "${var}\n${var//?/~}" Bölüm 2 - Kabuk ~~~~~~~~~~~~~~~ ${var:OFFSET:LENGTH} var değişkeninde OFFSET’ten itibaren LENGTH adet karakteri getirir [[email protected] ~]$ export var=abcdefgh [[email protected] ~]$ echo ${var:3:2} de Bölüm 2 Kabuk 16 | S a y f a İşletim Sistemleri [[email protected] ~]$ echo ${var:3} defgh 2.8 Aritmetik İşlemler Korn kabuğu ile çalışırken değişkenler üzerinde aritmetiksel ve mantıksal işlemler yapabiliriz. Aritmetik işlemler için toplama, çıkarma, çarpma, bölme ve bölümden kalan operatörlerini kullanabiliriz. Bu operatörlerin listesini Tablo-2.1’de bulabilirsiniz: Operatör İşlem Örnek Sonuç + Toplama ((x = 24 + 25)) 49 - Çıkarma ((x = 100 - 25)) 75 * Çarpma ((x = 4 * 5)) 20 / Bölme ((x = 10 / 3)) 3 % Bölümden Kalan ((x = 10 % 3)) 1 Tablo-2.1 Aritmetik İşlemler Korn kabuğunda tüm aritmetik işlemler tamsayı aritmetiği olarak gerçekleştirilir. Kayan noktalı sayılar için bir çözüm bulunmaz. Kayan noktalı sayılar ile işlem yapmak için bc komutunu kullanıyoruz. bc komutu bilimsel hesaplamalar da olmak üzere her türlü karmaşıklıktaki hesaplamalar için istenilen hassasiyette hesaplama yapılmasına izin verir: [[email protected] ~]$ echo "scale=8; a(1)*4" | bc -l 3.14159264 [[email protected] ~]$ echo "scale=16; a(1)*4" | bc -l 3.1415926535897932 [[email protected] ~]$ echo "scale=64; a(1)*4" | bc -l 3.1415926535897932384626433832795028841971693993751058209 749445920 [[email protected] ~]$ echo "scale=256; a(1)*4" | bc -l 3.1415926535897932384626433832795028841971693993751058209 74944592307\ 816406286208998628034825342117067982148086513282306647093 84460955058\ 223172535940812848111745028410270193852110555964462294895 49303819644\ 288109756659334461284756482337867831652712019091456484 Bölüm 2 Kabuk 17 | S a y f a İşletim Sistemleri Yukarıdaki örnekte PI sayısını istenilen basamak değerine kadar hesaplanabildiğini görüyoruz. Burada a(1), arctan trigonometrik fonksiyonunu göstermektedir. arctan(1) PI/4’dür. 2.9 Koşullu İfadeler Sonlanan her prosesin bir çıkış değeri bulunur. Bu değere göre prosesin başarılı olarak sonlanıp sonlanmadığı anlaşılabilir. 0 değeri işlemin başarıyla gerçekleştiğini gösterir. Sıfırdan her farklı değer işlemin başarısız olduğu anlamına gelir: [[email protected] /]$ if grep root /etc/passwd > then > echo "root bulundu." > fi root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin root bulundu. ya da [[email protected] /]$ if grep root /etc/passwd > /dev/null > then > echo "root bulundu." > fi root bulundu. Bir betiği belirli bir sayıda parametre ile çalıştırmak gerekiyorsa, bunun testi aşağıdaki gibi yapılabilir: if (( $# != 2 )) then print "KULLANIM: $0 arg1 arg2 " exit fi 2.10 Döngüler Döngü oluşturmak için birkaç yöntem bulunmaktadır. Bunlardan ilki for yapısını kullanmaktır: [[email protected] /]$ for meyve in elma portakal muz kavun karpuz > do > echo "Meyve: $meyve" > done Meyve: elma Meyve: portakal Meyve: muz Meyve: kavun Meyve: karpuz İkinci yöntem while yapısını kullanmaktır. while döngüsünde döngü koşulu doğru olana kadar döngü bloğu tekrar tekrar çalıştırılır. Aşağıdaki örnekte sayısal loto için 149 arasında biri birinden farklı altı sayı rastgele olarak belirlenmektedir: Bölüm 2 Kabuk 18 | S a y f a İşletim Sistemleri #!/bin/ksh (( r = RANDOM % 49 + 1 )) list="$r\n" for i in 2 3 4 5 6 ; do while true ; do (( r = RANDOM % 49 + 1 )) echo "$list" | grep "^$r$" > /dev/null if (( $? != 0 )) ; then break fi done list="$list\n$r" done list=$(echo "$list" | sort -n) echo $list Üçüncü yöntem until yapısını kullanmaktır. until döngüsünde while döngüsünün tersine, test koşulu yanlış olduğu sürece döngü döner: #!/bin/ksh num=1 until (( num == 6 )) do echo "The value of num is: $num" (( num = num + 1 )) done print "Done." Dizi kullanan örnek bir döngü uygulamasını inceleyelim: #!/bin/ksh for i in 1 2 3 4 5 6 ; do ((r= $RANDOM % 49 + 1)) numbers[$i]=$r done for j in ${numbers[*]} ; do echo $j done | sort -n Bu örnekte, ilk for döngüsünde sayısal loto için 1-49 arasında altı sayı rastgele olarak belirlenmekte ve numbers isimli dizide saklanmaktadır. İkinci for döngüsünde ise numbers dizindeki değerler taranarak, sıralı olacak şekilde ekrana yazılmaktadır. Sıralama işlemi için sort komutundan yararlanılmıştır. sort komutunun sayısal değer olarak değerlendirmesi ve sıralaması için –n seçeneği verilmiştir. 2.11 Fonksiyonlar Çok sık karşılaşılan problemlerin çözümünü fonksiyon olarak ayrı bir dosyada saklayabilirsek, aynı problemle tekrar karşılaştığımız betikte fonksiyonu çağırarak çözüme hızlıca ulaşabiliriz. Fonksiyonlar betiklerimizden ayrı dosyalarda bir dizinde Bölüm 2 Kabuk 19 | S a y f a İşletim Sistemleri saklanırlar. Bu dosyaların çalıştırma yetkisine de sahip olması gerekmez. Kabuğa, fonksiyonların yer aldığı bu dosyaların dizinini, FPATH sistem değişkeni ile tanıtıyoruz: [[email protected] ~]$ mkdir fun [[email protected] ~]$ export FPATH=$HOME/fun Bu dizinde sadece fonksiyon dosyalarının olmasına dikkat etmelisiniz. Fonksiyon ismi ile dosya ismi aynı olmalıdır. Fonksiyonun genel yazımı aşağıdaki gibidir: function hello { print “Merhaba $1” } Burada function anahtar kelimedir. Her fonksiyonun bir adı olmalıdır. Yukarıdaki örnekte fonksiyonun adı hello’dur. Fonksiyonlar parametre alabilirler. Fonksiyonun aldığı parametrelere erişmek için $ sembolünden yararlanıyoruz. İlk parametreye ulaşmak için $1’i ikinci parametreye ulaşmak için ise $2 tanımlamasını kullanıyoruz. Dokuzuncu parametreden sonra kıvırcık parantez kullanılmalıdır. Örneğin onuncu parametre için ${10} gösterimi kullanılmalıdır. [[email protected] fun]$ pwd /home/student/fun [[email protected] fun]$ ls hello [[email protected] fun]$ cat hello function hello { print "Merhaba $1" } Şimdi hello isimli fonksiyonu kullanacağımız basit bir betik yazalım: [[email protected] ~]$ cat test_hello.ksh #!/bin/ksh lost[1]="Jack Shephard" lost[2]="Kate Austen" lost[3]="James Ford" IFS=, for name in ${lost[*]} do hello $name done [[email protected] ~]$ ./test_hello.ksh Merhaba Jack Shephard Merhaba Kate Austen Merhaba James Ford Yukarıdaki örnekte lost dizisine üç değer atadık. Bu nedenle döngü üç defa döndü ve hello fonksiyonu üç defa çalıştırıldı. Bölüm 2 Kabuk 20 | S a y f a