Thread overview
arkaplanda servis olarak çalıştırma
Oct 10, 2013
darkofpain
Oct 11, 2013
darkofpain
October 10, 2013

Merhaba,

yaptığım uygulamayı normalde çift tıkladığımız zaman terminalde acılır ve program calışır ancak terminali kapattığımız zaman programda sonlanır.

yaptığım uygulamayı ./bin klasörüne yerleştirdim terminalede program yazdığım zaman çalışıyor ancak yine terminali kapatınca uygulama kapanıyor bu yüzden yaptığım uygulamayı program -start dediğim paylaşmasını ve arkaplanda çalışmasını istiyorum terminali kapatsam dahi program çalışacak.

ancak kapatmam gerektiğinde terminale program -stop dediğimde programı sonlandırıp kapatacak

bu olayı nasıl yapabilirim arkadaşlar.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 10, 2013

Yanılmıyorsam bu konu Windows'da Windows Service diye geçiyor:

http://msdn.microsoft.com/en-us/library/9k985bc9.aspx

Linux dünyasında da böyle programlara daemon deniyor. Google'da bulduğumuz C örneklerini herhalde D'ye çevirerek deneyebiliriz.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 11, 2013

valla c ile ilgili örnek bulamadım o yüzden d ile nasıl olur bilemiyorum da bu işin bu kadar zor olması tuhaf.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 11, 2013

Ben "linux daemon in c" diye aratıyorum. Google sonuçları herkese aynı göstermiyor diye bana çıkan bir örneğin sonundaki iki referans sayfayı göstereyim:

http://www.netzmafia.de/skripten/unix/linux-daemon-howto.html

http://blog.emptycrate.com/node/219

Zaman bulunca ben de bir örnek yazarım.

Alıntı:

>

bu işin bu kadar zor olması tuhaf

Kimse zaman ayırıp kolaylaştıran bir çözüm getirmediği için öyle. Bence 'servisleştir()' (veya 'daemonize()') diyeceğimiz bu işlevi sen yazacaksın. ;)

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 11, 2013

Oradaki bağlantıdan öğrendim ve aşağıdaki programı yazdım. Ana program servisin program kimliğini yazdırıyor ve sonlanıyor:

'İşçi başlatıldı: 20713'

İşçi program bağımsızca SIGTERM (15) sinyalini alana kadar çalışmaya devam ediyor. (O sinyali göndermek için neden root olunması gerektiğinden emin değilim ama sudo yazmazsam bende sonlanmıyor.):

'$ sudo kill 15 20713'

İşçi program kayıtlarını /tmp/Servis_denemesi_kayitlari diye bir dosyaya yazıyor:

'$ cat /tmp/Servis_denemesi_kayitlari
Servis oldum
Servis döngüsüne giriyorum
0
1
2
Servis döngüsünden çıktım
'

Program:

import std.stdio;
import std.exception;
import core.sys.posix.unistd;
import core.sys.posix.signal;
import core.sys.posix.sys.stat;
import core.thread;

bool devam_mı = true;

int main()
{
   pid_t kimlik = fork();

   if (kimlik < 0) {
       stderr.writeln("HATA: fork başarısız");
       return 1;
   }

   if (kimlik > 0) {
       // Bu durumda sahip programda devam etmekteyiz. Başka bir şey
       // yapmamıza gerek yok; sahip sonlanmalı.
       writeln("İşçi başlatıldı: ", kimlik);

       // DÜZELTME: Bu satır araya sıkışmış. :) Ona tabii ki gerek yok.
       // Thread.sleep(30.seconds);

   } else {
       // Bu durumda işçi programdayız. Bu programı servis (daemon) haline
       // getirmemiz gerekiyor.
       File kayıt = servisiHazırla();
       servisiİşlet(kayıt);
   }

   return 0;
}

extern(C) void sonlanmaSinyali(int) nothrow @system
{
   devam_mı = false;
}

File servisiHazırla()
{
   // Dosyalara yazabilmeyi sağla
   umask(0);

   // Servis kayıt (log) dosyasını aç
   auto kayıt = File("/tmp/Servis_denemesi_kayitlari", "w");

   // Sahipsiz (orphan) bir program olmayalım diye işletim sistemi
   // çekirdeğinden bir oturum numarası ediniyoruz.
   pid_t oturumNumarası = setsid();
   if (oturumNumarası < 0) {
       enum mesaj = "HATA: Oturum numarası (SID) edinemedim";
       kayıt.writeln(mesaj);
       throw new Exception(mesaj);
   }

   // Programın geçerli bir klasör içinde çalışmakta olduğunu garanti
   // et. Linux standardına göre var olduğundan kesinlikle emin olduğumu
   // klasör / (root) klasörüdür.
   int hata = chdir("/");
   if (hata) {
       enum mesaj = "HATA: Çalışma klasörünü ayarlayamadım";
       kayıt.writeln(mesaj);
       throw new Exception(mesaj);
   }

   // Hem konsolu kullanamayacağımız için hem de güvenlik riski nedeniyle üç
   // standart akımı kapatmalıyız.
   stdin.close();
   stdout.close();
   stderr.close();

   // Sonlanma sinyaline hazırlan
   signal(SIGTERM, &sonlanmaSinyali);

   kayıt.writeln("Servis oldum");

   kayıt.flush();
   return kayıt;
}

void servisiİşlet(File kayıt)
{
   kayıt.writeln("Servis döngüsüne giriyorum");

   // Servisin ana döngüsü
   for (size_t sayaç = 0; devam_mı; ++sayaç) {
       kayıt.writeln(sayaç);
       kayıt.flush();
       Thread.sleep(1.seconds);
   }

   kayıt.writeln("Servis döngüsünden çıktım");
}

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 12, 2013

Alıntı (acehreli:1381540883):

>

İşçi program bağımsızca SIGTERM (15) sinyalini alana kadar çalışmaya devam ediyor. (O sinyali göndermek için neden root olunması gerektiğinden emin değilim ama sudo yazmazsam bende sonlanmıyor.):

'$ sudo kill 15 20713'

Ha ha! Yanlış yazmışım. 15 numaralı sinyali göndereceğim diye yanlışlıkla 15 numaralı programı sonlandırmışım! :) Şöyle olmalı:

'$ kill -s 15 20713'

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 13, 2013

Bu kodu sınıf halinde düzenledim. Servis olmak isteyen bir program Servis sınıfından türetilmeli ve işlet() işlevini tanımlamalı.

import std.stdio;
import std.exception;
import core.sys.posix.unistd;
import core.sys.posix.signal;
import core.sys.posix.sys.stat;
import core.thread;

// ========== Bu bölüm servis.d modülü ==========
bool devam_mı = true;

extern(C) void sonlanmaSinyaliAlındı(int) nothrow @system
{
   devam_mı = false;
}

// Not: Aynı programda birden fazla Servis nesnesinin çalışabileceğini
//      sanmıyorum. Eğer gerçekten öyleyse bunun önlenmesi de gerekir.

class Servis
{
   string kayıtDosyasıİsmi;
   File kayıt;

   this(string kayıtDosyasıİsmi)
   {
       this.kayıtDosyasıİsmi = kayıtDosyasıİsmi;
   }

   pid_t başla()
   {
       pid_t kimlik = fork();
       enforce (kimlik >= 0, "fork başarısız");

       if (kimlik > 0) {
           // Bu durumda sahip programda devam etmekteyiz. Başka bir şey
           // yapmamıza gerek yok.

       } else {
           // Bu durumda işçi programdayız. Bu programı servis (daemon)
           // haline getirmemiz gerekiyor.
           hazırlan();

           mesajEkle("Servis işlemlerini başlatıyorum");
           işlet();
           mesajEkle("Servis işlemleri bitti");
       }

       return kimlik;
   }

   void hazırlan()
   {
       // Dosyalara yazabilmeyi sağla.
       umask(0);

       // Servis kayıt (log) dosyasını aç; dış dünyayla tek iletişimimiz bu
       // olacak.
       kayıt = File(kayıtDosyasıİsmi, "w");

       void denetle(bool koşul, string mesaj)
       {
           if (!koşul) {
               mesajEkle(mesaj);
               throw new Exception(mesaj);
           }
       }

       // Sahipsiz (orphan) bir program olmayalım diye işletim sistemi
       // çekirdeğinden bir oturum numarası edin.
       pid_t oturumNumarası = setsid();
       denetle(oturumNumarası >= 0, "Oturum numarası (SID) edinemedim");

       // Programın geçerli bir klasör içinde çalışmakta olduğunu garanti
       // et. Linux standardına göre var olduğundan kesinlikle emin olunan
       // klasör / (root) klasörüdür.
       int hata = chdir("/");
       denetle(hata == 0, "Çalışma klasörünü değiştiremedim");

       // Hem konsolu kullanamayacağımız için hem de güvenlik riski nedeniyle
       // üç standart akımı kapatmalıyız.
       stdin.close();
       stdout.close();
       stderr.close();

       // Sonlanma sinyalini almaya hazırlan.
       signal(SIGTERM, &sonlanmaSinyaliAlındı);

       mesajEkle("Servis oldum");
   }

   void mesajEkle(T...)(T mesajlar)
   {
       kayıt.writeln(mesajlar);
       kayıt.flush();
   }

   // Servis olmak isteyen bir programın yapması gereken, Servis'ten türetmek
   // ve soyut işlet() işlevinin o servise uygun bir tanımını vermektir.
   abstract void işlet();
}

// ========== Bundan sonrası da o modülü kullanan örnek bir program ==========

// Bir servis tanımlıyoruz
class BenimServis : Servis
{
   this()
   {
       // Yapmamız gereken, üst sınıfın istediği kayıt dosyası ismini vermek
       super("/tmp/Servis_denemesi_kayitlari");
   }

   // Bir de kendi işimize uygun bir işlet() işlevi yazmak
   override void işlet()
   {
       // Bu, servisin ana döngüsü. 'devam_mı' değişkeni servis.d modülü
       // tarafından sunuluyor.
       for (size_t sayaç = 0; devam_mı; ++sayaç) {
           mesajEkle(sayaç);
           Thread.sleep(1.seconds);
       }
   }
}

void main()
{
   auto servis = new BenimServis();

   pid_t işçiKimliği = servis.başla();
   writeln("İşçi başlatıldı: ", işçiKimliği);
}

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 13, 2013

Alıntı (acehreli):

>
> // Not: Aynı programda birden fazla Servis nesnesinin çalışabileceğini
> //      sanmıyorum. Eğer gerçekten öyleyse bunun önlenmesi de gerekir.
> ```


Bu konudaki deneyimsizliğimi sergilemeye devam ediyorum. :) Yukarıda söylediğim doğru değil çünkü her *fork*'ta bağımsız bir program ortaya çıkıyor. Dolayısıyla, her birisinin 'devam_mı' değişkenleri de bağımsız. Yani, aynı program birden fazla Servis oluşturabilir. (Sanırım. :-p)

Ali

-- 
[ Bu gönderi, <http://ddili.org/forum>'dan dönüştürülmüştür. ]