İçeriğe geç
academia.sh

Ders 02 / 24

Yönlendirme

Yönlendirme işleçleri, kesme ile ekleme farkı, tanıtıcı çoğaltma ve sıranın önemi, üzerine yazma tuzakları.

İçindekiler

Önceki ders akışların uçlarının değiştirilebilir olduğunu gösterdi ama değiştirme gösterimini kuralıyla açıklamadı. 2>/dev/null yazıldığında kabuk tam olarak ne yapar, > ile >> neden farklıdır, iki akışı tek dosyada toplarken sıra neden önemlidir?

Yönlendirme, kabuğun komutu çalıştırmadan önce yaptığı bir iştir. Komut başlamadan tanıtıcılar bağlanır; komut, uçlarının değiştirildiğini hiç fark etmez. Bu dersin tüm kuralları bu tek cümleden türer.

Kesme ve Ekleme

Standart çıktıyı dosyaya bağlayan iki işleç vardır.

> kesme (truncate) yapar: dosya yoksa yaratılır, varsa içeriği silinir. Yönlendirme komut çalışmadan uygulandığı için, komut hiçbir şey yazmasa bile dosya boşalır.

echo "birinci" > not.txt
echo "ikinci" > not.txt
cat not.txt
ikinci

>> ekleme (append) yapar: yazma konumu her seferinde dosyanın sonuna alınır.

echo "birinci" > not.txt
echo "ikinci" >> not.txt
cat not.txt
birinci
ikinci

Kesmenin komuttan bağımsız olması, bir dosyayı boşaltmanın en kısa yolunu verir. : yerleşik komutu hiçbir şey yapmaz ve hiçbir şey yazmaz; yönlendirme yine de uygulanır:

: > not.txt
wc -c not.txt
       0 not.txt

Bir kütük dosyasını sıfırlamanın doğru yolu budur. Dosyayı silip yeniden yaratmak yerine içeriğini boşaltmak, dosyayı açık tutan süreçlerin yazmaya devam etmesini sağlar; silinen dosyanın tanıtıcısı geçerli kalır ama yazılanlar hiçbir dizinden erişilemez olur.

Girdi Yönlendirme

< işleci, standart girdiyi bir dosyaya bağlar. Önceki derste görüldüğü gibi bu, dosya adını argüman olarak vermekle aynı şey değildir: komut yalnızca bir akış görür.

sort < erisim.log | head -2
10.0.0.12 - - [07/Feb/2024:09:12:44 +0000] "GET /index.html HTTP/1.1" 200 5120
10.0.0.12 - - [07/Feb/2024:09:13:02 +0000] "GET /urun/12 HTTP/1.1" 200 8410

Girdi yönlendirmesi dosyayı yalnızca okumaya açar; var olmayan bir dosya verilirse komut hiç çalıştırılmaz ve kabuk hata bildirir.

Tanıtıcı Numarasıyla Yönlendirme

Yönlendirme işleçlerinin önüne yazılan sayı, hangi tanıtıcının bağlanacağını söyler. Sayı yazılmazsa çıktı yönlendirmelerinde 1, girdi yönlendirmesinde 0 varsayılır. Dolayısıyla > dosya ile 1> dosya aynıdır.

ls erisim.log yok.txt >var.txt 2>hata.txt

var.txt yalnızca veriyi, hata.txt yalnızca tanı iletisini alır:

erisim.log
ls: yok.txt: No such file or directory

Sayı ile işleç arasında boşluk bulunamaz: 2 > hata.txt yazılırsa kabuk 2 dizgisini komuta argüman olarak geçirir ve yalnızca standart çıktıyı yönlendirir.

Tanıtıcı Çoğaltma ve Sıra

n>&m gösterimi yönlendirme değil çoğaltmadır (duplication): n numaralı tanıtıcı, m numaralının o an gösterdiği yeri gösterecek biçimde ayarlanır. Bu bir bağlantı kopyalamadır; sonradan m değişse bile n eski yerde kalır.

Kural buradan çıkar: yönlendirmeler soldan sağa uygulanır. İki akışı aynı dosyada toplamanın doğru yazımı önce hedefi belirlemek, sonra çoğaltmaktır.

ls erisim.log yok.txt >hepsi.txt 2>&1
cat hepsi.txt
ls: yok.txt: No such file or directory
erisim.log

Sıra ters çevrilirse sonuç değişir:

ls erisim.log yok.txt 2>&1 >ayri.txt

Bu çağrıda önce 2, o anki 1’in gösterdiği yere — yani terminale — bağlanır. Sonra 1 dosyaya çevrilir, ama 2 terminalde kalmıştır. Terminale şu düşer:

ls: yok.txt: No such file or directory

ayri.txt ise yalnızca veriyi alır:

erisim.log

Bu, yönlendirmenin en sık yapılan hatasıdır. Yazılışları birbirine benzeyen iki gösterimden biri “her şeyi dosyaya”, diğeri “hataları eski yere, veriyi dosyaya” anlamına gelir.

Bash, ilk durumun kısaltması olarak &> dosya yazımını da tanır. Kısa olmakla birlikte POSIX kabuk dilinde tanımlı değildir; taşınabilir olması gereken betiklerde >dosya 2>&1 yazımı tercih edilir. Aynı biçimde &>> ekleme yapar.

İki Yere Birden Yazmak

Yönlendirme tek hedef alır. Çıktının hem dosyaya kaydedilmesi hem de bir sonraki komuta akması gerektiğinde tee kullanılır: standart girdisinden okuduğunu hem verilen dosyalara hem de standart çıktısına yazar.

head -2 erisim.log | tee ilk-iki.txt | wc -l
       2

ilk-iki.txt içeriği:

10.0.0.12 - - [07/Feb/2024:09:12:44 +0000] "GET /index.html HTTP/1.1" 200 5120
10.0.0.31 - - [07/Feb/2024:09:12:51 +0000] "GET /statik/stil.css HTTP/1.1" 200 2048

tee -a dosyayı keserek değil ekleyerek yazar. Kurs sonunda yazılacak raporlama betiğinde tee, hem ekrana hem kütüğe yazmak için kullanılacak.

Üzerine Yazma Koruması

> işlecinin var olan dosyayı sessizce silmesi, elle yazılan komutlarda veri kaybının yaygın nedenidir. noclobber seçeneği bu davranışı kapatır:

set -o noclobber
echo "a" > n.txt      # dosya yok, yaratılır
echo "b" > n.txt      # dosya var, reddedilir
bash: n.txt: cannot overwrite existing file

Koruma açıkken bilinçli üzerine yazma >| ile yapılır:

echo "c" >| n.txt
cat n.txt
c

noclobber etkileşimli oturum için yararlıdır; betiklerde ise güvenilmez bir dayanaktır, çünkü betiği çalıştıran kabuğun ayarına bağlıdır. Betikte üzerine yazmayı engellemek istiyorsanız dosyanın varlığını açıkça sınayın — koşul sınamaları Betik Yapısı konusunda ele alınacak.

Aynı Dosyayı Okuyup Yazmak

Yönlendirmenin komuttan önce uygulanması, tek bir kuralı kaçınılmaz kılar: bir komutun girdi dosyası ile çıktı dosyası aynı olamaz.

printf 'c\nb\na\n' > kucuk.txt
sort kucuk.txt > kucuk.txt
wc -c kucuk.txt
       0 kucuk.txt

Dosya boşaldı. Kabuk kucuk.txt dosyasını kesti, sonra sort çalıştı ve okuyacak hiçbir şey bulamadı. Veri geri getirilemez.

Bu yüzden yerinde dönüştürme yapan araçlar (akış editörünün -i seçeneği gibi) dosyayı doğrudan değiştirmez; geçici dosyaya yazıp sonunda yer değiştirir. Aynı işi elle yapmak gerektiğinde izlenecek desen şudur:

sort kucuk.txt > kucuk.yeni && mv kucuk.yeni kucuk.txt

&& işleci, soldaki komut başarılı bitmediyse sağdakini çalıştırmaz; böylece sort hata verdiğinde özgün dosya yerinde kalır. Bu işlecin tam anlamı bu konunun son dersinde tanımlanacak.

Betiğin Tümünü Yönlendirmek

exec yerleşik komutu, komut adı verilmeden yalnızca yönlendirmelerle çağrılırsa, yönlendirmeleri kabuğun kendisine uygular. O noktadan sonraki tüm komutlar yeni uçları kullanır.

exec 3>&1 1>kayit.txt    # 1'in eski yerini 3'te sakla, 1'i dosyaya çevir
echo "dosyaya"
exec 1>&3 3>&-           # eski yeri geri yükle, 3'ü kapat
echo "ekrana"

Terminale yalnızca ikinci satır düşer:

ekrana

kayit.txt içeriği:

dosyaya

3>&- gösterimi tanıtıcıyı kapatır. Üç ve üzeri numaralı tanıtıcılar bu tür geçici saklama için serbesttir; kabuk onlara anlam yüklemez. Bu desen, bir betiğin tüm çıktısını kütüğe alıp yalnızca özeti terminale döndürmek için kullanılır ve kursun sonunda zamanlanmış görev yazarken işe yarayacak.

Özet

  • Yönlendirme komut çalışmadan önce uygulanır; komut, tanıtıcılarının nereye bağlandığını bilmez.
  • > hedefi keser, >> sonuna ekler; kesme komuttan bağımsız olduğu için : > dosya bir dosyayı boşaltır.
  • İşlecin önündeki sayı hangi tanıtıcının bağlanacağını belirler; n>&m çoğaltmadır ve yönlendirmeler soldan sağa uygulandığı için >dosya 2>&1 ile 2>&1 >dosya farklı anlamlara gelir.
  • Tek çıktının iki hedefe gitmesi gerektiğinde tee kullanılır.
  • Bir komutun girdi ve çıktı dosyası aynı olamaz; doğru desen geçici dosyaya yazıp yer değiştirmektir.

Sonraki Adım

Yönlendirme, akışın ucuna bir dosya koyar. Asıl bileşim gücü ise ucuna başka bir komut konduğunda ortaya çıkar. Sonraki ders boru hattını ele alır: komutların eşzamanlı çalışması, verinin arada dosyaya uğramadan akması ve bu düzenin getirdiği iki tuzak — zincirin çıkış kodu ve alt kabukta kaybolan değişkenler.

İ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