İçeriğe geç
academia.sh

Ders 05 / 20

Komut Yolu

Çalıştırılabilir arama sırası, ortam değişkenlerinin süreçlere aktarımı, komut karma tablosu ve bulunulan dizinin arama listesine neden eklenmediği.

İçindekiler

Önceki derste bir adın türü type ile belirlendi ve file yanıtı alındığında karşılığın bir dosya olduğu söylendi. Ancak ls yazıldığında tam yol verilmez; kabuk dosyayı bir yerde bulur.

Bu ders o aramanın kuralını açar. Aynı kural, bir komutun neden bulunamadığını, aynı adın iki farklı programa denk gelebileceğini ve bulunulan dizindeki bir programın neden doğrudan çalışmadığını birlikte açıklar.

Ortam Değişkenleri

Her sürecin, adlarla değerleri eşleyen bir ortam (environment) tablosu vardır. Süreç yeni bir süreç yarattığında bu tablo kopyalanarak aktarılır; çocuk süreç ortamı miras alır, ancak yaptığı değişiklik ebeveyne geri işlemez.

$ env | grep -E '^(HOME|PATH|PWD|SHELL|LANG|LC_ALL)='
PWD=/home/ogrenci
HOME=/home/ogrenci
LC_ALL=C
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

Kabukta tanımlanan her değişken ortama girmez. Sıradan bir atama yalnızca kabuk değişkeni oluşturur; bu değişken çalıştırılan programlara aktarılmaz. Değişkenin ortama girmesi için export ile işaretlenmesi gerekir. Ayrım şudur: kabuk değişkeni kabuğun kendi belleğindedir, ortam değişkeni çocuk süreçlere kopyalanır.

Bu kursta üç ortam değişkeni doğrudan kullanılır: HOME ev dizininin yolunu, PWD çalışma dizinini, PATH ise komut arama listesini tutar. LC_ALL gibi yerelleştirme değişkenleri komut çıktılarının dilini ve sıralama düzenini etkiler; bu kursun çıktıları için standart ayarda tutulmuştur.

Arama Sırası

Kabuk bir komut adı gördüğünde sabit bir sırayla karar verir:

  1. Ad bir anahtar sözcük mü? (if, for, while)
  2. Ad bir takma ad (alias) mı?
  3. Ad bir kabuk işlevi mi?
  4. Ad bir yerleşik komut mu?
  5. Değilse PATH listesindeki dizinlerde aranır.

İlk dördü kabuğun kendi belleğindedir ve dosya sistemine hiç bakılmaz. Beşinci adım diskte arama yapar.

PATH değişkeni iki nokta üst üste ile ayrılmış dizin yollarından oluşur. Kabuk bu dizinleri soldan sağa tarar ve adı taşıyan, çalıştırma izni olan ilk dosyayı seçer. Kalan dizinlere bakmaz. Hiçbir dizinde bulunmazsa 127 çıkış durumuyla “command not found” verir.

Sıranın soldan sağa olması, arama listesindeki konumun bir öncelik anlamına geldiğini söyler.

Gölgeleme

Aynı ad birden çok dizinde bulunabilir. Bu durumda listede önce gelen kazanır ve diğerini gölgeler. Etki, ayrı bir dizin kurularak gösterilebilir:

$ mkdir -p /tmp/deneme
$ printf '#!/bin/sh\necho sahte surum\n' > /tmp/deneme/date
$ chmod +x /tmp/deneme/date
$ type -a date
date is /usr/bin/date
date is /bin/date
$ PATH="/tmp/deneme:$PATH"
$ type -a date
date is /tmp/deneme/date
date is /usr/bin/date
date is /bin/date
$ date
sahte surum

type -a adı taşıyan tüm karşılıkları sırayla listeler; ilk satır çalıştırılacak olandır. Yeni dizin listenin başına eklendiğinde sistemin date komutu erişilemez hâle gelmemiştir — yalnızca arama sırasında sonraya düşmüştür.

Gölgeleme hem bir araç hem bir risktir. Araçtır: bir komutun kendi sürümü, sistem sürümüne dokunmadan öne alınabilir. Risktir: yazılabilir bir dizin arama listesinin başındaysa, o dizine dosya yazabilen herkes komut adlarını ele geçirebilir. Bu nedenle arama listesine eklenen dizinlerin yazma izinleri, izinler konusunda ele alınacak ölçütle değerlendirilmelidir.

Deneme dizini işi bittiğinde kaldırılır; kalıcı bırakılan böyle bir dizin sonraki oturumlarda beklenmedik davranışa yol açar.

Bulunulan Dizin Listede Değildir

PATH içinde bulunulan dizin (.) yer almaz. Bunun doğrudan bir sonucu vardır: bir dizindeki programı çalıştırmak için yol belirtmek gerekir.

$ pwd
/home/ogrenci/proje/betik
$ ozet.sh
bash: ozet.sh: command not found
$ echo $?
127
$ ./ozet.sh
ham olcum dosyasi: 0

ozet.sh ile ./ozet.sh arasındaki fark, kabuğun bakış açısındandır. Birincisi eğik çizgi içermeyen bir addır; kabuk onu PATH listesinde arar ve bulamaz. İkincisi eğik çizgi içerir; kabuk bunu bir yol sayar, arama yapmaz ve doğrudan o dosyayı çalıştırır.

Bulunulan dizinin listeye alınmaması bilinçli bir güvenlik kararıdır. Alınsaydı, herkesin yazabildiği bir dizinde ls adında bir dosya bırakmak, o dizine giren herkesin bu dosyayı çalıştırması için yeterli olurdu. Arama listesi bu nedenle sabit ve denetimli dizinlerden oluşur.

Bulunulan dizin listeye eklenecekse hiç değilse sona eklenir; sistem komutlarını gölgeleyemeyeceği konum orasıdır.

Çalıştırma İzni

Bir dosyanın PATH üzerindeki bir dizinde bulunması yetmez; çalıştırılabilir olarak işaretlenmiş olması gerekir.

$ ls -l ozet.sh
-rw-r--r-- 1 ogrenci ogrenci 139 Jul 26 18:49 ozet.sh
$ ./ozet.sh
bash: ./ozet.sh: Permission denied
$ echo $?
126
$ chmod +x ozet.sh
$ ls -l ozet.sh
-rwxr-xr-x 1 ogrenci ogrenci 139 Jul 26 18:49 ozet.sh
$ ./ozet.sh
ham olcum dosyasi: 0

İki çıkış durumu ayrı sorunları bildirir: 127 dosya bulunamadı, 126 bulundu ama çalıştırılamadı. chmod +x komutu çalıştırma iznini ekler; izin bitlerinin ne anlama geldiği ve -rwxr-xr-x dizesinin nasıl okunacağı izinler konusunun ilk dersinde kurulacaktır.

Betiğin ilk satırındaki #!/bin/sh gösterimi, dosyanın hangi yorumlayıcıyla çalıştırılacağını çekirdeğe bildirir. Çekirdek bu satırı okur ve belirtilen programı çağırıp dosyayı ona argüman olarak verir. Bu nedenle bir kabuk betiği, çalıştırılabilir ikili dosya olmadığı hâlde doğrudan çalıştırılabilir.

Çıktıda görülen 0 sayısı, ham ölçüm dizininin henüz boş olduğunu bildirir; sonraki konu bu dizini doldurmakla başlayacaktır.

Karma Tablosu

PATH her komut için baştan taranırsa, sık kullanılan komutlarda tekrarlanan dizin okuması olurdu. Kabuk bunu bir karma tablosunda bulduğu yolları saklayarak önler.

$ PATH="$HOME/proje/betik:$PATH"
$ type ozet.sh
ozet.sh is /home/ogrenci/proje/betik/ozet.sh
$ ozet.sh
ham olcum dosyasi: 0
$ type ozet.sh
ozet.sh is hashed (/home/ogrenci/proje/betik/ozet.sh)
$ hash
hits	command
   2	/home/ogrenci/proje/betik/ozet.sh
$ hash -r
$ type ozet.sh
ozet.sh is /home/ogrenci/proje/betik/ozet.sh

İlk çağrıdan sonra type yanıtı değişir: yol artık tabloda kayıtlıdır. Bunun bir yan etkisi vardır — bir program taşındığında veya silindiğinde kabuk eski yolu kullanmayı sürdürebilir ve “no such file or directory” hatası verebilir. hash -r tabloyu temizler ve aramayı yeniden yaptırır.

Bu davranış, Veri Yapıları kursundaki karma tablosunun tipik bir kullanımıdır: tekrarlanan pahalı bir aramanın sonucu saklanır, karşılığında saklanan bilginin eskiyebilme riski kabul edilir.

Arama Listesini Kalıcı Genişletmek

Kabukta yapılan PATH ataması yalnızca o oturum içindir. Kalıcı olması için, oturum açılırken okunan bir yapılandırma dosyasına yazılması gerekir:

$ tail -2 ~/.profile
PATH="$HOME/proje/betik:$PATH"
export PATH

~/.profile oturum açılışında okunan kullanıcı yapılandırma dosyasıdır. Yeni bir oturumda etki görünür:

$ echo "$PATH"
/home/ogrenci/proje/betik:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
$ ozet.sh
ham olcum dosyasi: 0

Atamada eski değerin $PATH ile korunması önemlidir. PATH="$HOME/proje/betik" biçiminde bir atama listeyi ezerdi ve sistem komutlarının hiçbiri bulunamazdı. Bu, geri dönüşü zahmetli bir hatadır: hata düzeltilene kadar ls dahil çoğu komut çalışmaz, düzeltme için tam yol yazmak gerekir.

Özet

  • Kabuk bir adı sırasıyla anahtar sözcük, takma ad, işlev, yerleşik komut olarak arar; bulamazsa PATH dizinlerini soldan sağa tarar.
  • İlk eşleşen dosya kazanır; aynı adın diğer karşılıkları gölgelenir ve type -a ile görülür.
  • Bulunulan dizin PATH içinde değildir; oradaki bir programı çalıştırmak için ./ öneki gerekir ve bu, yazılabilir dizinlerdeki komut ele geçirmelerine karşı bir önlemdir.
  • Dosyanın bulunması yetmez; çalıştırma izni yoksa çıkış durumu 126 olur.
  • Kabuk bulduğu yolları karma tablosunda saklar; program taşındığında hash -r gerekir.
  • Kalıcı PATH değişikliği oturum açılışında okunan yapılandırma dosyasına yazılır ve eski değer korunmalıdır.

Sonraki Adım

Sistem tanındı, ağaç kuruldu, betik çalıştı — ama betiğin bildirdiği ölçüm sayısı hâlâ sıfır. Sonraki konu dosyaların kendisine iner: dizinler arasında nasıl gezinildiği, bir listeleme çıktısının her sütununun ne anlattığı ve proje/veri/ham dizininin nasıl doldurulacağı ele alınır.

İ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