UNIX Pipeline
UNIX Pipeline
Douglas McIlroy, işletim sistemindeki programların (veya parçacıkların) birer standart girdisinin ve standart çıktısının olması gerektiği fikrini aslında yukarıdaki örneklerde bahsettiğimiz gibi sadece dosya yönlendirme amacıyla geliştirmemiştir. McIlroy'un amacı, aslında programların birbirleriyle, arada geçici bir dosya veya kullanıcı müdahalesine gerek olmaksızın veri akışının sağlanmasıdır. Bunu yaparken de, bir programın çıktısının diğer programın girdisi olarak yönlendirilmesini kurgulamıştır. McIlroy bu metodolojiyi ilk defa 1973'te kurgulamıştır ve Ken Thompson,pipe()
sistem çağrısını UNIX versiyon 3 üzerinde uyarlamıştır. Bunu yaparken de yönlendirme işareti olarak|
kullanılmıştır. McIlroy, bu karakterin kullanımını Thompson'ın geliştirdiğini belirtir. Bu yatak çubuk, aslında bir boru (pipe) olarak düşünülünce, tıpkı bir su tesisatındaki boru hattı gibi, bir noktadan giren bilginin, diğer noktadan çıkmasını sağladığı için pipeline terminolojisini doğurmuştur.
Örneğinless
programı, aslında kendisine sağlanan bilginin terminal ekranına sığacak şekilde parçalanmasını sağlar. Tıpkıcat
programında olduğu gibi, parametrik kullanımla dosya adı belirtilebilir, veya standart girdi olarak veri sağlanabilir.
Eğer çok fazla dosya içeren bir dizin içerisindels -l
komutunu çalıştırırsak, standart çıktı içerisinde kaybolabiliriz. Bunun içinls -l
komutunun çıktısını,less
programına girdi olarak sunabiliriz. Bunun için yapmamız gereken tek şey, aralarında pipe işaretini kullanmak olacaktır.
Bu çıktının en altında görülen--More--
kısmı aslında,less
programının getirdiği bir sonuç. Aynı şekildeless
çalıştırıldıktan sonra, standart girdiden (klavyeden) herhangi bir input beklemektedir. Kısacasıless
programı devreye girdikten sonra eğer bir tuşa basarsak,ls -l
çıktısının geri kalanının ekranımıza sığdığı kadarını karşımızda görebiliriz.
Aslında buradaki notasyon şu şekilde işler.komut1 | komut2 | komut3
şeklinde -neredeyse- sonsuza kadar komutları birbirine bağlayabilirsiniz ("Neredeyse sonsuza kadar" olmasının sebebini File Descriptor bölümünde göreceğiz). Buradaki komutlar birbirinden farklı olabileceği gibi, birbirleriyle aynı da olabilir. Bu komutların birbirleriyle konuşabilmeleri için bilmeleri gereken bir şey de yoktur. McIlroy'un 2. maddede bahsettiği, farklı programların birbirleriyle konuşmasını sağlama düşüncesi de burada ortaya çıkar.
Örneğin, sistemimizdeki yüklü Python modüllerinin bulunduğu/usr/local/lib/python3.5/dist-packages
dizini içerisinde sonu.py
ile bitmeyen dosyaların sayısını öğrenmek istersek, aşağıdaki komut dizisini kullanabiliriz.
Buradaki ilk komut,ls /usr/local/lib/python3.5/dist-packages
çok tanıdık bir iş yapıyor: dizinin içeriğini listeliyor. Ancak içeriğini standart çıktıda göstermek yerine,grep
programına iletiyor.grep
ise standart girdiden okuduğu veriler üzerinde-v .py$
parametrelerini çalıştırıyor. Burada yaptığı iş, "sonu.py
ile biten dosyaları göstermemek". Detaylarına grep ve Regular Expressions bölümünde değineceğiz. Elimizde artık sonu.py
ile bitmeyen dosyaların bir listesi var, ancak bunu görüntelemek istemiyoruz, çünkü bunların sayısını öğrenmek istiyoruz. Öyleyse standart çıktısınıwc
(word count) programına iletiyoruz.wc -l
ile standart girdiden gelen verinin kaç satır olduğunu sayıyoruz, ve bu sonucu artık standart çıktıya yazıyoruz. Bu yüzden standart çıktı olarak 129 değerini görüyoruz.
Tahmin edeceğiniz gibi, burada elde ettiğimiz sayıyı standart çıktı yerine aşağıdaki gibi bir dosyaya da yönlendirebilirdik.
T-Pipe
Yaptığımız son örnekte, dosyaların sayısınıpaket_sayisi
isminde bir dosyaya yazdırdık. Ancak eğer bu dosya sayısını ekranda görmek istiyor, ancak dosyaların bir listesini bir dosyaya yazdırmak istiyor olsaydık?
Örneğin, eğer paketlerin listesini bir dosyaya yazdırmak isteseydik, sondaki word count komutunu kullanmayıp, grep'in standart çıktısını bir dosyaya yönlendirmemiz gerekecekti.
Öte yandan, paketlerin sayısını ekranda görmek için, daha önce kullandığımız komutu kullanmamız gerekirdi.
Bir akış içerisinde standart çıktıyı yönlendirmek yerine, birkaç parçaya bölme işini yapmak içintee
isimli program geliştirilmiştir. Örneğintee
kullanarak aşağıdaki komut dizisini yazarsak, yukarıdaki iki komutu ayrı ayrı çalıştırmamıza gerek kalmaz.
Gördüğünüz gibi, standart çıktıya yine word count programının sonucu olan 129 yazıldı. Ancak aradatee
programı,grep
'in çıktısınıpaket_listesi
dosyasına yazdı. Dosyanın baş kısmınahead
programıyla bakıp içeriğine göz atabiliriz.
tee
programı, aslında UNIX pipeline'ında bir T-Pipe görevi gördüğü için bu ismi almıştır. UNIX pipeline'ı aslında bir boru tesisatı gibi düşünülebilir, ismi de buradan gelir zaten. Yazılımlar birbirlerine borularla bağlıdır, ve akış tek yönlüdür. Soldan sağa doğru akış gerçekleşir. Eğer bu akış içerisinde bir dallanmaya ihtiyaç duyarsak, boru tesisatlarında olduğu gibi T şeklinde bir boru kullanmamız gerekir. Böylece akışı iki veya daha fazla dala ayırabiliriz. Programa birden fazla parametre verip, çıktının birden fazla dosyaya da yazdırılmasını sağlayabiliriz.
Kısacasıtee
programı, standart girdiden gelen veriyi, hem kendisine parametre olarak verilen dosyalara yazar, hem de standart çıktıya yönlendirir. Böylece kendi standart çıktısı hangi programa standart girdi olarak sunulmuşsa, komutların akışı devam edebilir.
Normal şartlar altında > işaretinin yaptığı gibi, kendisine parametre olarak verilen dosyaları silip üzerine yazar. Ancak bu dosyaların mevcut bilgilerini koruyup sonuna veri eklemesini istersek (append etmesini istersek)-a
parametresiyle çalıştırmak gerekir. Bu, standart çıktı yönlendirmedeki >> işaretinin karşılığı gibi düşünülebilir.
tee Örneği
Kullanımı hakkında, GNU Core Utils'de paylaşılan birkaç örnek fikir verebilir.
Örneğin herhangi bir dosyanın internetten indirilmesi ile dosyanın MD5 Checksum hesaplanmasının sağlanmasını bir arada yapmak için aşağıdaki komut incelenebilir.
Yukarıdaki komut VeriTeknik mirrorlarından CentOS 7 Minimal güncel versiyonunu indirir,tee
ile dosyacentos7.iso
olarak kaydedilir ancak standart çıktıya yazılan veritee
ilemd5sum
programına aktarılır ve MD5 Checksum hesaplandıktan sonracentos7.md5
dosyasına kaydedilir. Burada önemli olan noktalardan birisi, MD5 hesaplanması için verinin tamamının indirilmesinin beklenmemesidir. Veri indikçe md5sum
programına veri akacak ve hesaplama başlayacaktır. Dolayısıyla verinin önce diske yazılması beklenmemektedir. Verinin önce diske yazılmasını, sonramd5sum
programının diskten tekrar okumasını sağlamak için şöyle yapabilirdik:
Ancak burada işlemler sırayla yapılacağı için, UNIX Pipeline'ın avantajlarından hiçbir şekilde faydalanmamış olurduk.
Process Substitution
Eğer yukarıda indirdiğimiz dosyanın, indirilirken, aynı anda hem MD5 Checksum'ının, hem de SHA1 Checksum'ının hesaplanmasını isteseydik,tee
ile standart çıktıyı iki farklı programa yönlendirmemiz gerekecekti. Bu işleme process substitution denilir. Aşağıdaki örnek ile görülebilir.
Yukarıdaki komut dizisinin kritik noktası,tee >(sha1sum > centos7.sha1) >(md5sum > centos7.md5)
bölümüdür. Burada tee
, standart çıktısını iki farklı işleme daha yönlendirir. Bu işlemler parantez içinde belirtilir, ve daha önce gördüğümüz > işareti ile bu işlemlere yönlendirme yapılır. Burada dikkat edilmesi gereken nokta, > işareti ile ( arasında boşluk bulunmaması gerektiğidir. Öte yandansha1sum
vemd5sum
sonrasında gelen > işaretleri doğrudan bu programların standart çıktılarını yönlendirme amacıyla yazıldığından, boşluk konması problem yaratmaz, zaten parantez içinde kullanılma sebepleri de budur.
Sankitee
programı iki farklı dosyaya yazmak yerine, iki farklı işleme standart çıktıyı yönlendirmektedir. Burada dosya (file) yerine işlem (process) koyduğumuz için, bir değişiklik (substitution) işlemi yapmış olduk. Bu yüzden bu yönteme process substitution denilir. Bu örnekte de, indirme işleminin, SHA1 hesaplamasının ve MD5 hesaplamasının birbirlerini beklemediğini, işlemin paralel gerçekleştirildiğini hatırlatmakta fayda var.
Last updated