Bash kabuğunda betik yazmanın incelikleri — 4
Bu flood’da yine Linux işletim sisteminde Bash
kabuğunda (shell) çalıştırmak üzere yazılan betiklerden (script) bahsederek seriyi kapatacağız.
Bash
içerisinde Web sunucu, TCP sunucu, vb bir daemon çalıştırmamız gerektiğinde ana betiği meşgul etmemek için ilgili servis arka planda başlatılabilir. Bir programı arka planda başlatmak için komutun sonuna &
işareti konur, başlatılan programın PID
'si ekranda gösterilir.
Önceki flood’larda Bash
'in $?
değişkeninde koşturulan son prosesin çıkış değerini verdiğini söylemiştik. Benzer şekilde $!
değişkeninde de başlatılan son prosesin PID
'si tutulur. Aşağıdaki örnekte daemon olarak çalıştırılan web sunucunun PID
'si bu yöntem ile alınmıştır.
Daemon arka planda çalıştırıldıktan sonra betik içerisinde başka işlemler gerçekleştirilerek başlatılan daemon’ın da belirli bir süre sonra kapatılması gerekebilir. Daemon’ın PID
'si başlatılırken elde edildiği için daemon'a gerekli sinyal gönderilerek kapanması sağlanabilir.
Başka bir kullanım alanında ise batch
işlemler yapan ve uzun süren bir veya daha fazla prosesi arka planda başlatarak PID
'lerini kaydederek betik içerisinde bitmelerini bekleyebiliriz. wait
komutu ile kabuk tarafından çalıştırılan bütün proseslerin bitmesi beklenebilir.
Aşağıdaki Bash
betiğinde birer saniye aralıklarla ekrana dört kere yazı yazacak iki proses arka planda başlatılmış ve ana betik içerisinden wait
ile beklenmiştir. Bütün çocuk prosesler bittikten sonra wait
programı çıkış yapmış ve akış devam etmiştir.
wait
programının arka planda çalıştırılan proseslerin bitmesini bekleyebilmesi için başlatılan proseslerin parent
'i olması gerekir. Eğer prosesler nohup
, screen
ve disown
gibi programlarla çalıştırılıp kabuktan koparılırsa wait
ile takip edilemezler.
wait
programı başlatılan prosesleri toplu bir şekilde beklemeye olanak tanır ancak herhangi bir zamanda topluca başlatılan proseslerin hangilerinin bittiği ile ilgili bilgilendirme yapmaz. Bu ihtiyaca cevap vermek üzere çok güzel bir hile geliştirilmiştir. kill -0 <pid>
komutu aracılığıyla prosese 0
numaralı sinyal gönderilir. man
sayfasından da bakılabileceği üzere aslında 0
diye bir sinyal yoktur. Burada kill
komutu sadece verilen PID
ile ilgili hata kontrolü yapar ve proses yoksa 0
'dan farklı bir çıkış kodu üretir.
Aşağıdaki örnekte arka planda başlatılan prosesin bitip bitmediği kill -0 <PID>
komutu ile birer saniye aralıklarla kontrol edilmiştir.
Zaman zaman Bash
'te komutları gruplama ihtiyacı oluşur. Gruplanan komutların ayrı bir kabukta (sub-shell
) koşturulması için parantez (...)
, mevcut kabukta koşturulması için ise süslü parantez {...}
içine yazılması gerekir.
Komutların gruplanmasına örnek olarak bir komut hata verdiğinde birden fazla komutun koşturulması gerektiği durum verilebilir. Aşağıdaki örnekte çıkış kodu 1
olan /bin/false
programı çalıştıktan sonra koşturulmak üzere bir komut grubu verilmiştir.
Bash
, güncel olarak yoğunlukla konteynerların başlatma betiği olarak kullanılmaktadır. Betikler bazı kontrollerden sonra konteynerin çalıştıracağı asıl programı başlatmaktadırlar. Örnek olarak Postgres
konteynerinde parola boş geçilmişse Bash
ile kullanıcı uyarılmaktadır.
İşte bu noktada konteyner başlatma betiği, asıl programı bir sub-shell
'de çalıştırmak yerine exec
programı yardımıyla kendi prosesi tarafından çalışır hale getirir ve kendisi ölmüş olur. Bu sayede konteynere gönderilen sinyaller direkt olarak ilgili programa gönderilebilir.
Nadiren ise konteyner başlatma betiğinde exec
kullanılmaz ve bash
ana programı bir sub-shell
'de çalıştırır. Bu durumlarda bash
'in konteynere gelen sinyalleri yakalayarak ana prosese göndermesi gerekmektedir. Aşağıda bu işlemi gerçekleştiren bir betik verilmiştir.