İçeriğe geç
academia.sh

Ders 02 / 20

Kabuk Nedir

İstem, komut satırının sözcüklere ayrılması, açılımların komuttan önce yapılması, seçenek biçimleri, yerleşik komutlar ve çıkış durumu.

İçindekiler

Önceki ders kabuğu, komutları yorumlayan değiştirilebilir bir program olarak tanımladı. Bu tanım henüz bir şey açıklamaz: kabuk yazılan satırı tam olarak ne yapar?

Sorunun yanıtı, komut satırının en sık yapılan hatalarını da açıklar. Boşluk içeren bir dosya adı neden iki ayrı argümana bölünür, yıldız işaretini gerçekte kim yorumlar, bir komutun başarılı olup olmadığı nereden anlaşılır — hepsi tek bir ayrıştırma sürecinin sonucudur.

İstem

Kabuk, komut beklediğini istem (prompt) ile bildirir. İstemin içeriği yapılandırılabilir; kullanıcı adı, makine adı ve bulunulan dizin yaygın olarak gösterilir. Bu kursun örneklerinde istem tek bir karakterle gösterilir:

$ echo Merhaba
Merhaba

$ ile başlayan satırlar yazılan komuttur; altındaki satırlar komutun ürettiği çıktıdır. Belgelerde yerleşik bir gelenek vardır: sıradan kullanıcı istemi $, süper kullanıcı istemi # ile gösterilir. Bir belgede # ile başlayan komut görülürse, o komutun yönetici yetkisi gerektirdiği anlaşılır.

Satır Sözcüklere Bölünür

Kabuk satırı önce sözcüklere böler. Bölme, boşluk karakterleriyle yapılır ve ardışık boşluklar tek bir ayırıcı sayılır. İlk sözcük çalıştırılacak programın adıdır; kalan sözcükler ona argüman olarak geçirilir.

$ echo Merhaba    dunya
Merhaba dunya

Çıktıda dört boşluk yerine bir boşluk vardır. Bunun nedeni echo komutunun boşlukları sıkıştırması değildir: echo iki argüman almıştır — Merhaba ve dunya — ve onları tek boşlukla birleştirerek yazdırmıştır. Aradaki boşluklar echo çalışmadan önce yok olmuştur.

Argüman sayısı doğrudan sayılabilir:

$ dosya="olcum 01.csv"
$ set -- $dosya; echo $#
2
$ set -- "$dosya"; echo $#
1

$# argüman sayısını verir. Değişkenin değeri tırnaksız yazıldığında kabuk onu iki sözcüğe bölmüş, tırnak içinde yazıldığında tek sözcük olarak bırakmıştır. Boşluk içeren dosya adlarının neden tırnak içinde yazılması gerektiğinin nedeni budur; aksi hâlde komut, var olmayan iki dosya arar.

Aynı fark, sözcük sınırlarını görünür kılan bir yazdırma biçimiyle de gösterilebilir:

$ printf '[%s]\n' $dosya
[olcum]
[01.csv]
$ printf '[%s]\n' "$dosya"
[olcum 01.csv]

Açılımlar Komuttan Önce Yapılır

Sözcüklere bölme tek işlem değildir. Kabuk, program çalışmadan önce sözcükler üzerinde birkaç açılım (expansion) uygular. Bu kursta üçü kullanılır: değişken açılımı ($ad), dosya adı açılımı (*, ?) ve ev dizini açılımı (~).

Belirleyici nokta şudur: açılımı yapan kabuktur, çalıştırılan program değil. Program yalnızca açılım sonucunu görür.

$ echo /usr/bin/zc*
/usr/bin/zcat /usr/bin/zcmp
$ ls /usr/bin/zc*
/usr/bin/zcat  /usr/bin/zcmp

İki komut da aynı iki dosya adını üretmiştir. ls komutuna * karakteri hiç ulaşmamıştır; kabuk deseni eşleşen dosya adlarıyla değiştirmiş, ls iki hazır argüman almıştır. echo ile ls çıktısı arasındaki tek fark, ls sütun hizalaması yapmasıdır.

Bunun iki sonucu vardır. Birincisi, desen hiçbir dosyayla eşleşmezse kabuk deseni olduğu gibi bırakır ve program * içeren anlamsız bir ad alır. İkincisi ve daha önemlisi, bir komutun ne yapacağı önceden görülebilir: komutun başına echo yazmak, kabuğun üreteceği argüman listesini çalıştırmadan gösterir. Bu, silme işlemleri dersinde bir güvenlik alışkanlığına dönüşecektir.

Tırnak, açılımı da durdurur:

$ echo "/usr/bin/zc*"
/usr/bin/zc*

Çift tırnak dosya adı açılımını ve sözcük bölmeyi engeller, değişken açılımını engellemez. Tek tırnak hepsini engeller: tek tırnak içindeki metin harfi harfine korunur.

Seçenekler ve Argümanlar

Bir komut satırının argümanları iki türlüdür. Seçenek (option) komutun davranışını değiştirir ve gelenek olarak tire ile başlar; kalanlar komutun üzerinde çalışacağı nesnelerdir.

Seçeneklerin üç yazım biçimi vardır ve üçü de aynı sonucu verir:

$ ls -l -a /home
total 16
drwxr-xr-x 1 root    root    4096 Jul 26 18:53 .
drwxr-xr-x 1 root    root    4096 Jul 26 18:46 ..
drwxr-x--- 3 ogrenci ogrenci 4096 Jul 26 18:49 ogrenci
$ ls -la /home
total 16
drwxr-xr-x 1 root    root    4096 Jul 26 18:53 .
drwxr-xr-x 1 root    root    4096 Jul 26 18:46 ..
drwxr-x--- 3 ogrenci ogrenci 4096 Jul 26 18:49 ogrenci

Tek harfli seçenekler tek tire ile yazılır ve birleştirilebilir: -l -a ile -la aynı şeydir. Uzun seçenekler iki tire ile yazılır (--all) ve birleştirilemez; her biri ayrı sözcüktür. Uzun seçenek biçimi POSIX’te tanımlı değildir, GNU araç ailesinin eklentisidir; taşınabilir olması gereken yerlerde tek harfli biçim tercih edilir.

Tire ile başlayan bir dosya adı varsa sorun çıkar: komut onu seçenek sanır. Bunun için -- ayıracı vardır. -- sözcüğünden sonrası seçenek olarak yorumlanmaz. Bu ayıracın neden bir güvenlik konusu olduğu, silme dersinde görülecektir.

Yerleşik Komut ve Dış Program

Her komut ayrı bir program değildir. Bazı komutlar kabuğun kendi içinde gerçekleştirilmiştir; bunlara yerleşik komut (builtin) denir. Bir adın hangisi olduğu sorulabilir:

$ type -a cd pwd echo
cd is a shell builtin
pwd is a shell builtin
pwd is /usr/bin/pwd
pwd is /bin/pwd
echo is a shell builtin
echo is /usr/bin/echo
echo is /bin/echo

Üç farklı durum görünür. cd yalnızca yerleşiktir. pwd ve echo hem yerleşiktir hem de dış program olarak vardır; bu durumda yerleşik olan kazanır.

cd’nin yerleşik olması bir tercih değil, zorunluluktur. Bir programın çalışma dizini kendi sürecine aittir; ayrı bir program olarak çalışan cd, kendi dizinini değiştirip sonlanır ve kabuğun dizini olduğu yerde kalırdı. Dizin değiştirmek için komutun kabuğun kendi süreci içinde çalışması gerekir.

echo’nun hem yerleşik hem dış program olması ise taşınabilirlik içindir: kabuğu olmayan ortamlarda da çağrılabilmesi gerekir. İki gerçekleştirimin davranışı tam olarak aynı değildir; bu nedenle biçimli çıktıda echo yerine printf tercih edilir.

Çıkış Durumu

Her komut sonlandığında geriye bir tam sayı bırakır: çıkış durumu (exit status). Sözleşme tersine kuruludur — sıfır başarıyı, sıfırdan farklı her değer bir başarısızlığı bildirir. Tek bir başarı, sayısız başarısızlık türü olduğu için bu yön seçilmiştir.

Son komutun durumu $? değişkeninde tutulur:

$ true; echo $?
0
$ false; echo $?
1
$ ls /yokdizin; echo $?
ls: cannot access '/yokdizin': No such file or directory
2

ls başarısızlığı hem bir hata iletisiyle hem de sıfırdan farklı bir durumla bildirir. İleti insan içindir; durum kodu, komutları birbirine bağlayan betikler içindir.

İki değer kabuğun kendisinden gelir ve ayırt edilmesi gerekir:

$ lss -l
bash: lss: command not found
$ echo $?
127

127 komutun bulunamadığını, 126 bulunduğunu ama çalıştırılamadığını bildirir. Birincisi bir arama sorunudur, ikincisi bir izin sorunu. Bu iki sayının farkı, sonraki dersin ve izinler konusunun tam olarak neyi çözdüğünü gösterir.

Hata iletilerinin nereye yazıldığı da ayrı bir konudur: normal çıktı ile hata çıktısı iki ayrı akıştır ve birbirinden bağımsız yönlendirilebilir. Bu ayrımın kullanımı Kabuk Programlama kursuna aittir.

Özet

  • Kabuk satırı önce sözcüklere böler; ilk sözcük program adı, kalanlar argümandır.
  • Değişken, dosya adı ve ev dizini açılımları program çalışmadan önce kabukta yapılır; program yalnızca sonucu görür.
  • Çift tırnak sözcük bölmeyi ve dosya adı açılımını durdurur, değişken açılımını durdurmaz; tek tırnak hepsini durdurur.
  • Tek harfli seçenekler birleştirilebilir, uzun seçenekler birleştirilemez; -- ayıracı seçenek yorumlamasını bitirir.
  • Yerleşik komutlar kabuğun kendi sürecinde çalışır; cd bu nedenle yerleşik olmak zorundadır.
  • Çıkış durumunda sıfır başarıyı gösterir; 127 komutun bulunamadığını, 126 çalıştırılamadığını bildirir.

Sonraki Adım

Komutlar artık üzerinde çalışacak dosyalara ihtiyaç duyar. Ancak dosyalar rastgele yerleştirilmemiştir: kök dizinden başlayan hiyerarşinin her dalının belirli bir anlamı vardır. Sonraki ders bu yerleşimi tanıtır, mutlak ve göreli yol ayrımını kurar ve kurs boyunca geliştirilecek proje ağacını oluşturur.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat