- Katılım
- 24 Şubat 2018
- Mesajlar
- 24,718
Shell (kabuk) programlama denince artık akla büyük ölçüde BASH için yazılmış script'ler gelir. Bu konuda, bir sunucu gibi çalışan ve hafızada sürekli olarak duran bir "sunucu" script'i ile buna komut gönderen bir "istemci" script nasıl yapabileceğimize bakacağız. Burada sunucu sürekli olarak komut bekliyor olacak ve bir komut alınca, bunun gereğini yapacak ve tekrar komut beklemeye başlayacak. Birden fazla istemci aynı anda komut gönderebiliyor olacak ve sunucu bunların ikisini de alıp gereğini yapabiliyor olacak.
Böyle bir sunucuyu shell programlama ile genel anlamda aşağıdaki metotlarla yapabiliriz:
1) Sunucunun, belli bir dizini gözlemesini, ve bu dizin içerisine bir dosya oluşturulursa, bu dosyayı okuyup içindeki komutu işleyebilir. Komut işlendikten sonra da dosya silinebilir. Bu yöntem, basit gibi görünse de, beklenmedik zorlukları vardır. Örneğin istemcilerin, kesinlikle farklı isimli bir dosya kullanmaları lazım, yoksa bir istemci, diğer istemcinin komut dosyasının üzerine yazabilir. İkinci zorluk, yeni bir dosya oluştuğunun algılanmasıdır. Burada genellikle "inotify" mekanizması kullanılır. Ama inotify kullanıldğında da, sadece bu program aktif iken değişiklikler rapor edilir. Bir değişiklik algılanıp gereği yapılmak üzere inotify çıktığında, artık yeni bir dosya oluştuğunu farkedemeyiz. Dizini tarayabiliriz, ama tam biz taramayı yaptıktan sonra yeni bir komut dosyası gelebilir. Bu zorluklar nedeniyle, bu yöntemi elememiz lazım.
2) Sunucuya "signal" göndermek. Mesela X komutu için SIGUSR1, Y komutu için SIGUSR2, Z komutu için SIGHUP kullanılabilir. Ama bu yöntemin de en büyük sıkıntısı, hem gönderilecek komutlar kısıtlı, hem komutlara parametre veremiyoruz, hem de bir komut bitmeden yeni komut gönderemiyoruz. O yüzden bu metot da hemen elenebilir.
3) Belli bir mekanizma ile bir komutu alıp onu stdout'a yazan özel bir program kullanmak. Bu metot çok güzel işe yarar tabiki. Mesela socket'ler üzerinden komut alan bu program, bir döngü içerisinde sürekli olarak script'e komutları besleyebilir. Ama böyle özel bir programı shell dışında başka bir dil ile yazdıysak, o zaman shell ile niye uğraşıyoruz? direkt bütün işi o programlama dilinde bitirelim O yüzden bu metot da eleniyor.
4) "named pipe" kullanmak. İşte bu metot, tamamen shell script dahilinde bize çok güzel bir çözüm sunuyor. Ama bunu doğru bir şekilde çalışır hale getirmek için birçok detay vardır.
İşte bu konuda 4 numaralı çözümü aşama aşama anlatacağız. Önce en basit bir şekilde gerçekleştireceğiz, ortaya çıkan problemleri gözlemleyeceğiz ve bu problemleri ortadan kaldıran daha gelişmiş çözüme geçeceğiz.
Böyle bir sunucuyu shell programlama ile genel anlamda aşağıdaki metotlarla yapabiliriz:
1) Sunucunun, belli bir dizini gözlemesini, ve bu dizin içerisine bir dosya oluşturulursa, bu dosyayı okuyup içindeki komutu işleyebilir. Komut işlendikten sonra da dosya silinebilir. Bu yöntem, basit gibi görünse de, beklenmedik zorlukları vardır. Örneğin istemcilerin, kesinlikle farklı isimli bir dosya kullanmaları lazım, yoksa bir istemci, diğer istemcinin komut dosyasının üzerine yazabilir. İkinci zorluk, yeni bir dosya oluştuğunun algılanmasıdır. Burada genellikle "inotify" mekanizması kullanılır. Ama inotify kullanıldğında da, sadece bu program aktif iken değişiklikler rapor edilir. Bir değişiklik algılanıp gereği yapılmak üzere inotify çıktığında, artık yeni bir dosya oluştuğunu farkedemeyiz. Dizini tarayabiliriz, ama tam biz taramayı yaptıktan sonra yeni bir komut dosyası gelebilir. Bu zorluklar nedeniyle, bu yöntemi elememiz lazım.
2) Sunucuya "signal" göndermek. Mesela X komutu için SIGUSR1, Y komutu için SIGUSR2, Z komutu için SIGHUP kullanılabilir. Ama bu yöntemin de en büyük sıkıntısı, hem gönderilecek komutlar kısıtlı, hem komutlara parametre veremiyoruz, hem de bir komut bitmeden yeni komut gönderemiyoruz. O yüzden bu metot da hemen elenebilir.
3) Belli bir mekanizma ile bir komutu alıp onu stdout'a yazan özel bir program kullanmak. Bu metot çok güzel işe yarar tabiki. Mesela socket'ler üzerinden komut alan bu program, bir döngü içerisinde sürekli olarak script'e komutları besleyebilir. Ama böyle özel bir programı shell dışında başka bir dil ile yazdıysak, o zaman shell ile niye uğraşıyoruz? direkt bütün işi o programlama dilinde bitirelim O yüzden bu metot da eleniyor.
4) "named pipe" kullanmak. İşte bu metot, tamamen shell script dahilinde bize çok güzel bir çözüm sunuyor. Ama bunu doğru bir şekilde çalışır hale getirmek için birçok detay vardır.
İşte bu konuda 4 numaralı çözümü aşama aşama anlatacağız. Önce en basit bir şekilde gerçekleştireceğiz, ortaya çıkan problemleri gözlemleyeceğiz ve bu problemleri ortadan kaldıran daha gelişmiş çözüme geçeceğiz.