Şeytan, Pengueni Dürterse

28 Mart 2010

Günümüzde birçok site arkada yapılacak görevleri çalıştırmak için görev yöneticileri kullanılır. Crontab (Zaman ayarlı) ve Daemon (kendi halinde çalışan) iki görev yöneticinin arasındaki bence tek fark (durum bu kadar basit olmasada) Crontab’ın 1 dakikanın altındaki süreçlere göre çalışmamasıdır. Bu görevler için Daemon denilen ve /etc/init.d altında tetiklenen ve sinyallerle çalıştırılıp durdurulabilen ve process id değeri üreten bir teknolojiye ihtiyaç duymasıdır. Daemon’lar init.d altında bir çalıştırıcı scripte sahip olmaya bilir ama durdumak istendiğinde güç kullanılarak öldürülmesi (kill)  gerekir ki, kritik işlerde bu pek tehlikeli bir yöntemdir. Init.d altındaki başlatma scripti bir proses(PID) dosya yaratır ve daemon’u çalıştırır. Sonrasında durdumak isterse daemon’a sinyal gönderir. Böylece uygulama durma sinyalini görünce düzgün bir şekilde sonlanır. Crontab ise belli bir işin bellir bir saatte yapılmasını sağlar. Saatte bir, her 15 dk.’da bir ayın 5. günü, her çarşamba saat 15′te gibi…

Kullanım alanlarına birkaç örnek vermek gerekirse;

Daemon; Özellikle kuyruktaki işleri işlemek için çok kullanılır.

  • Video converter
  • Email/SMS gönderme
  • RSS ayrıştırma.

Cron;

  • Günde bir kez gönderilecek işler. Örneğin; doğum günü epostaları.
  • Ayda hatta yılda bir kez yapılacak işler. Anneler gününde temanın otomatik olarak değiştirilmesi.
  • Haftanın belli bir günü yapılacak olan işler. Her Pazartesi indirim puanı oluşturup, rastgele 500 üyeye gönderme.
  • Saatte bir yapılacak işler, Site için RSS oluşturma.

Daemon yazmak genelde C dili ile yazılan işlerdendir. Çünkü bu iş hem performans hem de sistem programlama(sinyaller ve prosesler) bilgisi  gerekir. Buna rağmen, işin mantığı ise  PHP, ve benzeri web dillerinde yazılmıştır. Belki de biraz bu sebeplerle Crontab ile görev tanımı yapılır. Crontab kullanmak güzeldir ama kurulum sürecinde ek yük getirir. Bunların doğru bir şekilde çalıştığının kaydının tutulması (loging) ve gözlenmesi (monitoring) işlerinin yapılmasıda cabası.

Bu yazı Chronical projesinin bilgi tasarımının ilk taslaklarını içermesinin yanında aktif olan mevcut uygulamalardan örnekler de verilecektir.

Peki bu işleri ne şekilde yapımak gerekir?

1) System_Daemon PEAR Paketi

PEAR kütüphanesi içerisinde bulunan ve Kevin van Zonneveld tarafından geliştirilen System_Daemon paketi kolayca linux daemonları yaratmanıza olanak verecek olan harika bir araçtır. Becerileri;

  1. İşletim sistemine özel başlangıç ayarlarının ve kurulumlarının kolayca yapılabilmesi.
  2. İşlem kaydı (loging) tutalbilmesi. Ve PEAR kütüphanesi ile uyumluluk
  3. Kullanım kolaylığı, birazdan örnek uygulamada da görebileceksiniz
  4. Sinyallerle çalışma ve özelleştirme

System Daemon Kurulum;

Linux sunucunuzda PEAR kurulu ise şu şekilde;

$ pear install -f System_Daemon

Yada şuradan indirerek kullanabilirsiniz.

Kullanım;

job/sms_sender.php isimli bir php dosyası yaratalım.

// Gerekli olan Daemon kütüphanesi.
// Bu kütüphane include_dir dizininin gösterdiği bir yerde olmalı.
require_once "System/Daemon.php";

// İzin verilen parametreler
$runmode = Array (
    // tek başına çalışması için
    'standalone' => false,
    // initd dizininde çalıştırma betiği yaratır.
    'write-initd' => false,
);

// Scan command line attributes for allowed arguments
foreach ($argv as $k=>$arg) {
    if (substr($arg, 0, 2) == '--' && isset($runmode[substr($arg, 2)])) {
        $runmode[substr($arg, 2)] = true;
    }
}

// appName minimum gerekli olan parametredir.
System_Daemon::setOption("appName", "sms_sender");

// System_Daemon::setOption ile tek tek  ya da
// System_Daemon::setOptions($options) ile toplu olarak girilebilir.

$options = array(
    //'appName' => 'sms_sender',
    'appDir' => dirname(__FILE__),
    'appDescription' => 'MT SMS Sender',
    'authorName' => 'Hasan Ozgan',
    'authorEmail' => 'hasan@ozgan.net',
    'sysMaxExecutionTime' => '0',
    'sysMaxInputTime' => '0',
    'sysMemoryLimit' => '1024M',
    'appRunAsGID' => 1000,
    'appRunAsUID' => 1000,
);
System_Daemon::setOptions($options);

// Eger daemon olarak çalışmayacaksa
// System_Daemon::start() methodu ile başlatılabilir.
if ($runmode["standalone"]) {
    System_Daemon::start();
}

// job --write-initd parametresi ile çalıştırıldığında kendini kaydeder.
// açılışta çalıştırıldığında ise --init.d parametresi alır.
if (!$runmode["write-initd"]) {
     System_Daemon::info('not writing an init.d script this time');
} else {
    if (($initd_location = System_Daemon::writeAutoRun()) === false) {
        System_Daemon::notice('unable to write init.d script');
    } else {
        // parametreli log örneği...
        System_Daemon::info(
            'sucessfully written startup script: %s',
            $initd_location
        );
    }
}

// Daemon stop sinyali gelene kadar çalışmaya devam eder.
while (!System_Daemon::isDying()) {
   // Buraya işinizle ilgili kodları eklemelisiniz.

   $messages = OutgoingSMS::fetchMessages();
   foreach ($messages as $message) {
       if (!$message->send()) {
            System_Daemon::error("Message not send");
       }
   }

   // Daemonlarda önemli olan sonsuz döngüde bir miktar
   // işlem yapıp sistemi dinlendirmek gerekir.
   // Bunun için ise iterate methodu ile saniye cinsinden
   // bir süre vererek çağrı yapmak gerekir.
   System_Daemon::iterate(5);
}

System_Daemon::stop();

Yazdığımız scripti tek başına çalıştırmak için ise;

$ job/send_sms --standalone

yazmamız yeterlidir. Service birkez çalışıp sonlanacaktır.

Servisimizi init.d altına kaydetmek için ise;

$ sudo job/send_sms --write-initd

yazmamız yeterlidir. Eğer burada hata alırsanız, init.d dizinin yazma haklarını kontrol etmeniz gerekir.

$ sudo chmod a+w /etc/init.d

Bu işlemleri yaptıktan sonra appName parametresinde girdiğimiz isme göre;

  • /etc/init.d/send_sms
  • /var/log/send_sms.log
  • /var/run/send_sms/send_sms.pid

dosyaları oluşturulur.
İşletim sisteminin açılışta servisi çalıştırması için kayıt etmek gerekir.

# kayıt için
$ sudo update-rc.d send_sms defaults
# kaldırmak için ise
$ sudo update-rc.d -f send_sms remove

2) Periodic Kütüphanesi

Arbit firması tarafından geliştirilen Periodic kütüphanesini kullanabilirsiniz. Bu kütüphane crontab işlerini kendi sarmalayan biraz daha karmaşık bir mimariye sahiptir.


 
  
     92384032
     92384032
  
  
     
  
  
     
  
  

Periodic ile ilgili daha detaylı bilgiyi şuradan alabilirsiniz.

3) Chronical Job Management Projesi

Bu proje benim yapacağım hem cron hem de daemon desteği ile melez çalışacak bir projedir. Henüz fikir halindedir. Projene adresine şuradan ulaşılabilir.

Bu proje servis işlerinizi hızlı ve kolay bir şekilde merkezi bir yerden yönetmeniz, durumunu kontrol etmenizi amaçlar.

Özellikleri

  • Yaml ile kolayca güncellenebilen ayar dosyası
  • Daemon kaydetme, kaldırmak ve durum bilgisi almak için kullanılacak çalıştırılabilir betik
  • İş mantığınızı barındıran kodları çalıştıracak Abstract sınıf.

Örnek proje ayar dosyası (task.config);

# Period Format
# second minute hour day month dayOfWeek weekOfMonth
# second: 0-59
# minute: 0-59
# hour: 0-23
# day: 1-31
# month: 1-12
# dayOfWeek: 1-7
# weekOfMonth: 1-5

# proje adina göre tek bir daemon oluşur.
# Bu daemon işlerin tamamını alt prosesler yaratarak yönetir.

proje_adi:
    gorev_adi:
        class: Application_Jobs_SmsSender
        # her 30 saniyede bir çalış anlamında.
        period: */30 * * * * *
    change_theme:
        class: Application_Jobs_ChangeTheme
        # Mayıs ayının ikinci pazar günü saat gece 2'de
        # Anneler gününde çalış.
        period: * 2 * 5 7 2

Arayüz Sınıfı

interface Chronical_Job_Interface
{
     // Ayar dosyasına verilen sınıfların bu
     // arayüzden gerçekleştirilmesi gerekir.
     public function run();
}

Örnek Sınıfı

class Application_Jobs_SendSms
                    extends Joy_Application
                    implements Chronical_Job_Interface
{
     public function run()
     {
           // TODO: Yapılacak işler....
     }
}

Örnek log ayar dosyası; Bu dosya chronical uygulamasının log ve pid ayarları ile ilgili bir dosyadır. Ubuntu ve debian temelli dağıtımlar için /etc/chronical.ini

[folders]
     folder.log = /var/log/
     fodler.pid = /var/run/
     folder.init.d = /etc/init.d
[defaults]
; seconds
     default.sleep_time = 5

Düşünülen betik dosyası örnek işler

# OS startup install for init.d
$ chronical install task.config

# OS startup uninstall for init.d
$ chronical uninstall task.config

# Görev çalıştırma
$ chronical start proje_adi:gorev_adi

# Görev durdurma
$ chronical start proje_adi:gorev_adi

# Görev durumunu görme
$ chronical status proje_adi:gorev_adi

Kısaca Unix sistemleri üzerinde daemon ve crontab işleri bu şekilde. (:

Kategori
Etiket



Eğer yazıyı beğendiyseniz ya da ekleyecekleriniz varsa, lütfen yorumunuz yazın veya RSS aboneliği ile yeni yazılardan anında haberdar olun.

'Şeytan, Pengueni Dürterse' için 4 Yorum

Onur YALAZI
Mart 28, 2010

job/sms_sender.php de 5inci satırda $rubmode yazılmış sanırım $runmode olması gerekiyor.

HasanOzgan
Mart 28, 2010

Teşekkür ederim Onur, düzelttim.

Halid
Mart 29, 2010

Makale için teşekkürler.

Ancak cron’u saniyelik bile çalıştırabilmek mümkün.

http://blog.halid.org/halidsaidaltuner/linux-unix/saniyelik-cron-eklemek-ve-varsayilan-crontab-editorunu-degistirmek/

HasanOzgan
Mart 29, 2010

Halid Cron hacking yapmışsınız. :) Konuya katkın için teşekkür ederim. Lakin Cron ile bu tür bir işlem yapmanın riski şu; uygulamayı güvenli olarak sonlandırdığından emin olamayabilirsin.

Yorum yapın