Ders 06 / 24
Betik Anatomisi
Yorumlayıcı bildirimi, çalıştırma izni, betiği çalıştırmanın üç yolu ve alt süreçle kaynak okuma arasındaki fark.
İçindekiler
Önceki konu, komutları akışlarla ve çıkış kodlarıyla birbirine bağlamayı kurdu. Ortaya çıkan hatlar tek satırlıktı: yazıldıkları anda çalıştılar ve kayboldular. Aynı hattı her gün çalıştırmak, üzerine seçenek eklemek ve başkasına devretmek gerektiğinde tek satır yetmez.
Betik (script), kabuğun okuyup sırayla yürüttüğü komutları tutan sıradan bir metin dosyasıdır. Bu ders dosyanın ne olduğunu, çekirdeğin onu nasıl çalıştırdığını ve üç farklı çalıştırma yolunun süreç açısından ne anlama geldiğini ele alır.
İlk Betik
Önceki dersin son hattı bir dosyaya alınır:
#!/usr/bin/env bash # rapor.sh — erisim kutugunden ozet rapor uretir. echo "== En cok istenen yollar ==" cut -d' ' -f7 erisim.log | sort | uniq -c | sort -rn | head -5
Bu dosya rapor.sh adıyla kaydedilir. Kurs boyunca her konu bu betiği bir adım
ilerletecek; sonunda argüman alan, hataya dayanıklı ve zamanlanmış olarak çalışan bir
araç hâline gelecek.
# ile başlayan satırlar yorumdur; kabuk onları yok sayar. Yorum işareti satır
başında olmak zorunda değildir ama kelime ortasında yorum başlatmaz:
echo abc#def echo abc #def
abc#def abc
Yorumun başlaması için # işaretinin bir kelimenin başında bulunması gerekir. Bu, dosya
adlarında ve URL’lerde # geçtiğinde işe yarayan bir kuraldır.
Çalıştırma İzni
Betik dosyası yaratıldığında çalıştırma izni taşımaz. Doğrudan çağrılırsa:
./rapor.sh
bash: ./rapor.sh: Permission denied
echo $?
126
Kod 126, “dosya bulundu ama çalıştırılamadı” anlamına gelir; önceki derste ayrılmış
kodlar arasında geçmişti. İzin verilir:
chmod +x rapor.sh ./rapor.sh
== En cok istenen yollar == 6 /api/veri 4 /yok.html 4 /index.html 3 /urun/45 3 /urun/12
Betiğin adının önündeki ./ bırakılırsa sonuç değişir:
rapor.sh
bash: rapor.sh: command not found
echo $?
127
Linux’a Giriş kursunun komut yolu dersinde kurulan kural burada işler: eğik çizgi
içermeyen bir ad, yalnızca PATH içindeki dizinlerde aranır ve bulunulan dizin bu
listede yer almaz. ./rapor.sh yazımı adı bir yol hâline getirir ve arama yapılmaz.
Bulunulan dizini PATH listesine eklemek yaygın bir öneri değildir: o dizine ls adında
bir dosya bırakan herkes, orada çalıştırdığınız her komutu ele geçirebilir.
Yorumlayıcı Bildirimi
Betiğin ilk satırındaki #! dizisi bir yorum gibi görünür ama işlevi kabuğun değil
çekirdeğin ilgi alanındadır. Dosyanın ilk iki baytı #! ise, çekirdek onu doğrudan
çalıştırmaya kalkmaz; satırın kalanını bir program yolu olarak okur, o programı başlatır
ve betik dosyasının yolunu ona argüman olarak verir.
Bu düzeneğe yorumlayıcı bildirimi (shebang) denir. Üç ayrıntısı vardır.
Yalnızca ilk satırda geçerlidir. İkinci satırdaki #! sıradan yorumdur. İlk satırın
ilk iki baytı #! değilse bildirim yoktur.
Yol saltıktır, arama yapılmaz. Çekirdek PATH bakmaz. #!/bin/bash yazan bir betik,
bash’in /bin/bash yolunda bulunmadığı bir sistemde çalışmaz.
Bildirim yoksa davranış çağırana kalır. Çekirdek dosyayı çalıştıramaz ve hata döndürür; bunun üzerine çağıran kabuk çoğu durumda dosyayı kendi alt kabuğuna okutur. Sonuç, betiği çalıştıran kabuğa bağlıdır — yani taşınabilir değildir.
printf 'echo "shebangsiz calisti: $0"\n' > yalin.sh chmod +x yalin.sh ./yalin.sh
shebangsiz calisti: ./yalin.sh
Çalıştı, ama hangi kabukla çalıştığı garanti değildir. Her betiğe yorumlayıcı bildirimi yazmak zorunlu bir alışkanlıktır.
Hangi Yorumlayıcı
İki yaygın yazım vardır ve seçim betiğin ne kullandığına bağlıdır.
#!/bin/sh, POSIX kabuk dilini bildirir. Bu yolun ucundaki programın hangi kabuk olduğu
sisteme göre değişir; verilen tek güvence, POSIX kabuk dilini yorumlayacağıdır. Dizi,
[[ ]], <<<, ${var,,} gibi bash eklentileri bu bildirimle kullanılamaz — bazı
sistemlerde çalışıyor görünmeleri yanıltıcıdır, çünkü orada /bin/sh bash’in POSIX
kipidir.
#!/usr/bin/env bash, env komutunu çağırarak bash’i PATH içinde arar. Bash’in
sistemden sisteme farklı yerlerde kurulu olması bu yazımla soğurulur. Bedeli, PATH
üzerinden dolaylı bir arama yapılmasıdır; sabit yol gerektiren sıkı ortamlarda
#!/bin/bash yeğlenir.
Karar kuralı: betikte bash’e özgü tek bir özellik kullanıyorsanız bash bildirin. POSIX bildirip bash özelliği kullanmak, betiğin başka bir sistemde sessizce bozulmasının en sık nedenidir. Bu kursta bash’e özgü her özellik metinde açıkça belirtilecek.
Bash sürümleri arasında da fark vardır. Bir sistemde /bin/bash eski bir ana sürüm
olabilir; ilişkisel diziler gibi özellikler orada yoktur. Diziler ve İlişkisel Diziler
dersinde bu farkın ölçülebilir bir örneği verilecek.
Çalıştırmanın Üç Yolu
Aynı betik üç farklı biçimde yürütülebilir ve üçü aynı şey değildir.
Doğrudan çalıştırma (./rapor.sh) çalıştırma izni ve yorumlayıcı bildirimi ister.
Yeni bir süreç yaratılır.
Yorumlayıcıya argüman olarak verme (bash rapor.sh) ne izin ne bildirim ister;
bildirim varsa da yok sayılır, çünkü dosya çalıştırılmaz, okunur. Yine yeni bir süreç
yaratılır.
Kaynak okuma (. rapor.sh veya source rapor.sh) yeni süreç yaratmaz. Komutlar
o anki kabuğun içinde yürütülür.
Üçüncüsünün farkı gözlemlenebilir. ayar.sh yalnızca bir değişken atasın:
KUTUK=erisim.log
bash ayar.sh echo "alt surec sonrasi: [${KUTUK-tanimsiz}]" . ./ayar.sh echo "source sonrasi: [${KUTUK-tanimsiz}]"
alt surec sonrasi: [tanimsiz] source sonrasi: [erisim.log]
Alt süreçte yapılan atama, süreçle birlikte kayboldu. Boru hattı dersindeki alt kabuk
davranışının aynısıdır: süreçler arasında değişken geçmez. Kaynak okuma bu yüzden
yapılandırma dosyaları ve fonksiyon kitaplıkları için kullanılır; iş yapan betikler için
uygun değildir, çünkü betiğin exit çağrısı çağıran kabuğu kapatır.
. yazımı POSIX’tir, source bash eklentisidir; ikisi aynı işi yapar. POSIX yazımında
dosya adı eğik çizgi içermiyorsa PATH içinde aranır — . ./ayar.sh yazımındaki ./
bu yüzden gereklidir.
Betiğin Çıkış Kodu
Bir betik, son çalıştırdığı komutun kodunu döndürür. Aşağıdaki betiğin son satırı
eşleşme bulamayan bir grep ise:
#!/usr/bin/env bash grep -q '999' erisim.log
./sonkod.sh; echo "kod=$?"
kod=1
Betik başarılı çalıştı ama başarısızlık bildirdi. Bu davranış istenmiyorsa kod açıkça
yazılır: exit 0. Çıkış kodunu bilinçli belirlemek, betiği bir zincirde ya da
zamanlanmış görevde kullanılabilir kılan şeydir.
Çalıştırmadan Sözdizim Denetimi
bash -n seçeneği betiği okur, ayrıştırır ama çalıştırmaz. Yarım kalmış bir yapı varsa
bildirir:
bash -n bozuk.sh
bozuk.sh: line 4: syntax error: unexpected end of file from `if' command on line 2
Bu denetim yalnızca sözdizimini görür; var olmayan komutları, yanlış seçenekleri veya mantık hatalarını yakalamaz. Yine de yıkıcı işlem içeren bir betiği ilk kez çalıştırmadan önce yapılacak en ucuz sınamadır. Hata ayıklama araçlarının tamamı Betik Hata Ayıklama dersinde ele alınacak.
Özet
- Betik, kabuğun sırayla yürüttüğü komutları tutan metin dosyasıdır;
#ile başlayan kelimeler yorum açar. - Doğrudan çalıştırma çalıştırma izni ister; izin yoksa kod 126, ad
PATHiçinde bulunamazsa 127 döner. - İlk iki baytı
#!olan dosyada çekirdek, satırın kalanındaki saltık yolu yorumlayıcı olarak başlatır; arama yapmaz ve yalnızca ilk satıra bakar. #!/bin/shyalnızca POSIX kabuk dilini güvence altına alır; bash eklentisi kullanan betik bash bildirmelidir.bash betikyeni süreç yaratır,. betikyaratmaz; ikincisinde atamalar çağıran kabukta kalır.
Sonraki Adım
Betiğin gövdesindeki kütük adı şimdilik sabit yazılı. Onu bir değişkene almak ilk bakışta yalnızca düzen meselesi görünür; oysa kabukta değişken genişletmenin sonucu tırnak kullanımına göre değişir ve tırnaksız bir genişletme, boşluk içeren dosya adlarında betiği sessizce yanlış çalıştırır. Sonraki ders genişletme, kelime bölme ve alıntılama kurallarını ele alır.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.