लिनक्स में एक डेमॉन बनाना


110

लिनक्स में मैं एक डेमॉन जोड़ना चाहता हूं जिसे रोका नहीं जा सकता है और जो फाइलसिस्टम में बदलाव की निगरानी करता है। यदि कोई परिवर्तन पाया जाता है, तो उसे कंसोल पर पथ लिखना चाहिए जहां इसे शुरू किया गया था और साथ ही एक नई पंक्ति।

मेरे पास पहले से ही फाइलसिस्टम बदलने वाला कोड लगभग तैयार है लेकिन मैं यह पता नहीं लगा सकता कि डेमॉन कैसे बनाया जाता है।

मेरा कोड यहाँ से है: http://www.yolinux.com/TUTORIALS/ForkExecProcesses.html

कांटे के बाद क्या करें?

int main (int argc, char **argv) {

  pid_t pID = fork();
  if (pID == 0)  {              // child
          // Code only executed by child process    
      sIdentifier = "Child Process: ";
    }
    else if (pID < 0) {
        cerr << "Failed to fork" << endl;
        exit(1);
       // Throw exception
    }
    else                                   // parent
    {
      // Code only executed by parent process

      sIdentifier = "Parent Process:";
    }       

    return 0;
}

1
संभावित डुप्लिकेट: stackoverflow.com/q/5384168/1076451
चिमरा

1
संभव डुप्लिकेट: stackoverflow.com/questions/5384168/… डेमनीज भाग के लिए, stackoverflow.com/questions/931093/… फाइलसिस्टम घड़ी के लिए
Ciro Santilli 郝海东 病 六四 六四 法轮功 法轮功

यदि आपको POSIX अनुपालन की आवश्यकता नहीं है, तो आपको inotifyAPI में रुचि हो सकती है। देखें: inotify_init, inotify_add_watch, inotify_rm_watch
patryk.beza

जवाबों:


216

लिनक्स में मैं एक डेमॉन जोड़ना चाहता हूं जिसे रोका नहीं जा सकता है और जो फाइलसिस्टम में बदलाव की निगरानी करता है। यदि किसी भी परिवर्तन का पता लगाया जाएगा, तो उसे कंसोल पर पथ लिखना चाहिए जहां इसे शुरू किया गया था + एक नई पंक्ति।

डेमॉन पृष्ठभूमि में काम करते हैं और (आमतौर पर ...) एक टीटीवाई से संबंधित नहीं होते हैं, इसलिए आप जिस तरह से संभवत: स्टैडआउट / स्टैडर का उपयोग नहीं कर सकते हैं। आमतौर पर एक syslog डेमॉन ( syslogd) ) का उपयोग संदेशों को फाइलों में प्रवेश करने के लिए किया जाता है (डीबग, त्रुटि, ...)।

इसके अलावा, एक प्रक्रिया को समाप्त करने के लिए कुछ आवश्यक कदम हैं।


अगर मुझे सही ढंग से याद है कि ये चरण हैं:

  • कांटा बंद माता पिता प्रक्रिया और इसे समाप्त करता है, तो forking के सफल रहा था करते हैं। -> क्योंकि पैरेंट प्रक्रिया समाप्त हो गई है, बच्चे की प्रक्रिया अब पृष्ठभूमि में चलती है।
  • setsid - एक नया सत्र बनाएँ। कॉलिंग प्रक्रिया नए सत्र के नेता और नई प्रक्रिया समूह के प्रक्रिया समूह के नेता बन जाती है। इस प्रक्रिया को अब इसके नियंत्रण टर्मिनल (CTTY) से अलग कर दिया गया है।
  • कैच सिग्नल - संकेतों को अनदेखा करना और / या संभालना।
  • फिर से कांटा और यह सुनिश्चित करने के लिए कि आप सत्र की अग्रणी प्रक्रिया से छुटकारा पा लेते हैं, पैरेंट प्रक्रिया को समाप्त कर दें। (केवल सत्र के नेताओं को फिर से एक TTY मिल सकता है।)
  • chdir - डेमॉन की कार्यशील निर्देशिका को बदलें।
  • umask - डेमॉन की जरूरतों के अनुसार फाइल मोड मास्क को बदलें।
  • करीब - सभी खुले फ़ाइल विवरणों को बंद करें जो मूल प्रक्रिया से विरासत में मिले।

आपको एक प्रारंभिक बिंदु देने के लिए: इस कंकाल कोड को देखें जो मूल चरणों को दर्शाता है। इस कोड को अब GitHub: linux daemon के बेसिक कंकाल पर भी कांटा जा सकता है

/*
 * daemonize.c
 * This example daemonizes a process, writes a few log messages,
 * sleeps 20 seconds and terminates afterwards.
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <syslog.h>

static void skeleton_daemon()
{
    pid_t pid;

    /* Fork off the parent process */
    pid = fork();

    /* An error occurred */
    if (pid < 0)
        exit(EXIT_FAILURE);

    /* Success: Let the parent terminate */
    if (pid > 0)
        exit(EXIT_SUCCESS);

    /* On success: The child process becomes session leader */
    if (setsid() < 0)
        exit(EXIT_FAILURE);

    /* Catch, ignore and handle signals */
    //TODO: Implement a working signal handler */
    signal(SIGCHLD, SIG_IGN);
    signal(SIGHUP, SIG_IGN);

    /* Fork off for the second time*/
    pid = fork();

    /* An error occurred */
    if (pid < 0)
        exit(EXIT_FAILURE);

    /* Success: Let the parent terminate */
    if (pid > 0)
        exit(EXIT_SUCCESS);

    /* Set new file permissions */
    umask(0);

    /* Change the working directory to the root directory */
    /* or another appropriated directory */
    chdir("/");

    /* Close all open file descriptors */
    int x;
    for (x = sysconf(_SC_OPEN_MAX); x>=0; x--)
    {
        close (x);
    }

    /* Open the log file */
    openlog ("firstdaemon", LOG_PID, LOG_DAEMON);
}
int main()
{
    skeleton_daemon();

    while (1)
    {
        //TODO: Insert daemon code here.
        syslog (LOG_NOTICE, "First daemon started.");
        sleep (20);
        break;
    }

    syslog (LOG_NOTICE, "First daemon terminated.");
    closelog();

    return EXIT_SUCCESS;
}


  • कोड संकलित करें: gcc -o firstdaemon daemonize.c
  • डेमॉन शुरू करें: ./firstdaemon
  • जांचें कि क्या सब कुछ ठीक से काम कर रहा है: ps -xj | grep firstdaemon

  • आउटपुट इस के समान होना चाहिए:

+ ------ + ------ + ------ + ------ + ----- + ------- + ------ + ------ + ------ + ----- +
| पीपीआईडी ​​| पीआईडी ​​| पीजीआईडी ​​| SID | टीटीवाई | TPGID | STAT | यूआईडी | समय | CMD |
+ ------ + ------ + ------ + ------ + ----- + ------- + ------ + ------ + ------ + ----- +
| 1 | 3387 | 3386 | 3386 | ? | -1 | एस | 1000 | 0:00 | ./ |
+ ------ + ------ + ------ + ------ + ----- + ------- + ------ + ------ + ------ + ----- +

आपको यहां क्या देखना चाहिए:

  • डेमन के पास कोई नियंत्रण टर्मिनल ( TTY =? ) नहीं है
  • मूल प्रक्रिया ID ( PPID ) 1 है (init प्रक्रिया)
  • पीआईडी! = सिड जिसका अर्थ है कि हमारी प्रक्रिया सत्र नेता नहीं है
    (दूसरा कांटा की वजह से ())
  • क्योंकि PID! = SID हमारी प्रक्रिया फिर से TTY का नियंत्रण नहीं ले सकती

Syslog पढ़ना:

  • अपनी syslog फ़ाइल का पता लगाएँ। मेरा यहाँ है:/var/log/syslog
  • एक करो: grep firstdaemon /var/log/syslog

  • आउटपुट इस के समान होना चाहिए:

  firstdaemon [3387]: पहला डेमॉन शुरू हुआ।
  फर्स्टडैम [3387]: पहला डेमॉन समाप्त हुआ।


एक नोट: वास्तव में आप सिग्नल हैंडलर को भी लागू करना चाहेंगे और लॉगिंग को ठीक से सेट करेंगे (फ़ाइलें, लॉग स्तर ...)।

आगे की पढाई:


वाह धन्यवाद! एक दम बढ़िया। इसलिए मुझे अपने कोड को लूप में डालना होगा और इसे करना होगा?
क्रिसम जूल 30'13

असल में, हाँ। लेकिन यह कोड एक उदाहरण मात्र है। यह पूरी तरह से इस बात पर निर्भर करता है कि आप डेमन प्रक्रिया का उपयोग करके क्या हासिल करना चाहते हैं । इस उत्तर को भी अवश्य पढ़ें: @Edwin
पास्कल वर्कल

1
दूसरे के बजाय fork(), सिर्फ उपयोग क्यों नहीं setsid()?
चमीरा

1
नोट है कि समारोह संकेतों को नियंत्रित करने के लिए एक अधिक व्यापक और विश्वसनीय तंत्र प्रदान करता है; नए अनुप्रयोगों के बजाय का उपयोग करना चाहिए sigaction()sigaction()signal()
patryk.beza

4
दर्शकों को ध्यान दिया जाना चाहिए कि यह तरीका "पुराना" तरीका है। डेमॉन बनाने का नया अनुशंसित तरीका यहां पाए जाने वाले "नए स्टाइल डेमॉन" के साथ है: 0pointer.de/public/systemd-man/daemon.html#New-Style%20Daemons या
स्टारबोर्ड

30

man 7 daemonमहान विस्तार में डेमॉन बनाने का वर्णन करता है। मेरा जवाब इस मैनुअल से सिर्फ अंश है।

कम से कम दो प्रकार के डेमॉन हैं:

  1. पारंपरिक SysV डेमन ( पुरानी शैली ),
  2. सिस्टमड डेमोंस ( नई शैली )।

SysV डेमोंस

यदि आप पारंपरिक SysV डेमन में रुचि रखते हैं , तो आपको निम्नलिखित चरणों को लागू करना चाहिए :

  1. मानक इनपुट , आउटपुट और त्रुटि (यानी पहले तीन फ़ाइल वर्णनकर्ता 0, 1, 2) को छोड़कर सभी खुले फ़ाइल विवरणों को बंद करें । यह सुनिश्चित करता है कि कोई गलती से पास की गई फाइल डिस्क्रिप्टर डेमन प्रक्रिया में इधर-उधर न रहे। लिनक्स पर, इसके माध्यम से पुनरावृत्ति करके इसे सर्वोत्तम रूप से लागू किया जाता है /proc/self/fd, फाइल डिस्क्रिप्टर 3 से पुनरावृत्ति के साथ इसके getrlimit()लिए लौटाए गए मान तक RLIMIT_NOFILE
  2. सभी सिग्नल हैंडलर को उनके डिफ़ॉल्ट पर रीसेट करें । यह सबसे अच्छा उपलब्ध संकेतों के माध्यम से पुनरावृत्ति करके _NSIGऔर उन्हें रीसेट करने के लिए सबसे अच्छा है SIG_DFL
  3. सिग्नल मास्क का उपयोग करके रीसेट करें sigprocmask()
  4. पर्यावरण चरों को हटाने या रीसेट करने के लिए पर्यावरण ब्लॉक को संजीवित करें, जो डेमन रनटाइम को नकारात्मक रूप से प्रभावित कर सकता है।
  5. कॉल करें fork(), एक पृष्ठभूमि प्रक्रिया बनाने के लिए।
  6. बच्चे में, setsid()किसी भी टर्मिनल से अलग होने के लिए कॉल करें और एक स्वतंत्र सत्र बनाएं ।
  7. बच्चे में, fork()फिर से कॉल करें, यह सुनिश्चित करने के लिए कि डेमन फिर से एक टर्मिनल को फिर से हासिल नहीं कर सकता है।
  8. exit()पहले बच्चे में कॉल करें , ताकि केवल दूसरा बच्चा (वास्तविक डेमॉन प्रक्रिया) चारों ओर रहे। यह सुनिश्चित करता है कि डेमन प्रक्रिया init / PID 1 में फिर से सम्‍मिलित है, जैसा कि सभी डेमन को होना चाहिए।
  9. डेमन प्रक्रिया में, /dev/nullमानक इनपुट , आउटपुट और त्रुटि से कनेक्ट करें ।
  10. डेमन प्रक्रिया में, umask0 को रीसेट करें , ताकि फ़ाइल मोड पास हो जाए open(), mkdir()और इस तरह सीधे बनाई गई फ़ाइलों और निर्देशिकाओं के एक्सेस मोड को नियंत्रित करें।
  11. डेमॉन प्रक्रिया में, बदलने के रूट निर्देशिका (करने के लिए वर्तमान निर्देशिका /बचने के लिए, क्रम में) कि डेमॉन अनायास ब्लॉक अनमाउंट होने से माउंट पॉइंट।
  12. डेमन प्रक्रिया में, डेमन पीआईडी ​​को (जैसा कि लौटाया जाता है getpid()) एक पीआईडी ​​फ़ाइल में लिखें , उदाहरण के लिए /run/foobar.pid(एक काल्पनिक डेमन "फोब्बर" के लिए) यह सुनिश्चित करने के लिए कि डेमन को एक से अधिक बार शुरू नहीं किया जा सकता है। इसे रेस-फ्री फैशन में लागू किया जाना चाहिए ताकि पीआईडी ​​फ़ाइल केवल तभी अपडेट हो जब यह उसी समय सत्यापित हो जाए कि पीआईडी ​​फाइल में पहले संग्रहीत पीआईडी ​​मौजूद नहीं है या किसी विदेशी प्रक्रिया से संबंधित है।
  13. डेमन प्रक्रिया में, यदि संभव हो तो और विशेषाधिकारों को छोड़ दें।
  14. डेमॉन प्रक्रिया से, मूल प्रक्रिया को सूचित करें कि प्रारंभ करना पूर्ण हो गया है। इसे एक अनाम पाइप या इसी तरह के संचार चैनल के माध्यम से लागू किया जा सकता है जो पहले fork()और मूल और डेमन प्रक्रिया दोनों में उपलब्ध है।
  15. exit()मूल प्रक्रिया में कॉल करें । डेमन को आमंत्रित करने वाली प्रक्रिया इस बात पर भरोसा करने में सक्षम होना चाहिए कि यह आरंभिक पूर्ण exit()होने के बाद होता है और सभी बाहरी संचार चैनल स्थापित और सुलभ होते हैं।

इस चेतावनी पर ध्यान दें:

बीएसडी daemon()फ़ंक्शन का उपयोग नहीं किया जाना चाहिए , क्योंकि यह इन चरणों का केवल सबसेट लागू करता है ।

एक डेमन जिसे SysV सिस्टम के साथ अनुकूलता प्रदान करने की आवश्यकता है, उसे ऊपर बताई गई योजना को लागू करना चाहिए। हालाँकि, डिबगिंग को कम करने के साथ-साथ सिस्टम का उपयोग करके सिस्टम में एकीकरण को आसान बनाने के लिए इस व्यवहार को कमांड लाइन तर्क के माध्यम से वैकल्पिक और विन्यास योग्य बनाने की सिफारिश की जाती है।

ध्यान दें कि POSIX अनुपालन daemon()नहीं है ।


न्यू-स्टाइल डेमोंस

नई शैली के डेमों के लिए निम्नलिखित चरणों की अनुशंसा की जाती है:

  1. यदि SIGTERMप्राप्त होता है, तो डेमॉन को बंद करें और सफाई से बाहर निकलें।
  2. यदि SIGHUPप्राप्त होता है, तो कॉन्फ़िगरेशन फ़ाइलों को पुनः लोड करें, यदि यह लागू होता है।
  3. मुख्य डेमॉन प्रक्रिया से एक सही निकास कोड प्रदान करें, क्योंकि इसका उपयोग init सिस्टम द्वारा सेवा त्रुटियों और समस्याओं का पता लगाने के लिए किया जाता है। SysV init स्क्रिप्ट के लिए LSB सिफारिशों में परिभाषित निकास कोड योजना का पालन करने की सिफारिश की गई है ।
  4. यदि संभव हो और लागू हो, डी-बस आईपीसी प्रणाली के माध्यम से डेमन के नियंत्रण इंटरफ़ेस को उजागर करें और आरंभीकरण के अंतिम चरण के रूप में बस नाम को पकड़ो।
  5. Systemd में एकीकरण के लिए, एक .service यूनिट फ़ाइल प्रदान करें जो डेमॉन को शुरू करने, रोकने और अन्यथा बनाए रखने के बारे में जानकारी प्रदान करती है। systemd.service(5)विवरण के लिए देखें।
  6. जितना संभव हो, फ़ाइलों, सेवाओं और अन्य संसाधनों के लिए डेमॉन की पहुंच को सीमित करने के लिए init सिस्टम की कार्यक्षमता पर भरोसा करें, यानी systemd के मामले में, अपने स्वयं के कार्यान्वयन के बजाय systemd के संसाधन सीमा नियंत्रण पर भरोसा करें, systemd के विशेषाधिकार छोड़ने पर भरोसा करें कोड को डेमन में लागू करने के बजाय, और इसी तरह। systemd.exec(5)उपलब्ध नियंत्रणों के लिए देखें ।
  7. यदि डी-बस का उपयोग किया जाता है, तो डी-बस सेवा सक्रियण कॉन्फ़िगरेशन फ़ाइल की आपूर्ति करके अपने डेमन बस-सक्रिय करें । इसके कई फायदे हैं: आपके डेमॉन को आलसी ऑन-डिमांड शुरू किया जा सकता है; इसकी आवश्यकता अन्य डेमॉन के समानांतर शुरू हो सकती है - जो समानांतरकरण और बूट-अप गति को अधिकतम करता है ; बिना किसी बस अनुरोध को खोए आपके विफलता को फिर से शुरू किया जा सकता है, क्योंकि सक्रिय सेवाओं के लिए बस कतार अनुरोध करती है। देखें नीचे जानकारी के लिए।
  8. यदि आपका डेमॉन एक सॉकेट के माध्यम से अन्य स्थानीय प्रक्रियाओं या दूरस्थ ग्राहकों को सेवाएं प्रदान करता है, तो इसे नीचे दी गई योजना के बाद सॉकेट-सक्रिय किया जाना चाहिए । डी-बस सक्रियण की तरह, यह ऑन-डिमांड सेवाओं को शुरू करने में सक्षम बनाता है और साथ ही यह सेवा स्टार्ट-अप के बेहतर समानांतरीकरण की अनुमति देता है। इसके अलावा, राज्य-कम प्रोटोकॉल (जैसे syslog, DNS) के लिए, सॉकेट-आधारित सक्रियण को लागू करने वाले एक डेमन को बिना किसी अनुरोध को खोए फिर से शुरू किया जा सकता है। देखें नीचे जानकारी के लिए।
  9. यदि लागू हो, तो एक डेमन को sd_notify(3)इंटरफ़ेस के माध्यम से स्टार्टअप पूर्णता या स्थिति अपडेट के बारे में इनिट सिस्टम को सूचित करना चाहिए ।
  10. syslog()सिस्टम syslog सेवा में सीधे लॉग इन करने के लिए कॉल का उपयोग करने के बजाय , एक नई शैली का डेमॉन केवल मानक त्रुटि के माध्यम से लॉग इन करने का चयन कर सकता है fprintf(), जिसे तब init सिस्टम द्वारा syslog में अग्रेषित किया जाता है। यदि लॉग स्तर आवश्यक हैं, तो ये लिनक्स की कर्नेल printk()स्तर प्रणाली के समान शैली का अनुसरण करते हुए, "<4>" (जैसे syslog प्राथमिकता योजना में लॉग स्तर 4 "चेतावनी") के लिए व्यक्तिगत लॉग लाइनों को प्रीफ़िक्स करके एन्कोड किया जा सकता है। विवरण के लिए, देखें sd-daemon(3)और systemd.exec(5)

और जानने के लिए पूरे पढ़ा man 7 daemon


11

आप linux में एक प्रक्रिया नहीं बना सकते जिसे मार नहीं सकते। रूट उपयोगकर्ता (uid = 0) एक प्रक्रिया को एक संकेत भेज सकता है, और दो संकेत हैं जिन्हें पकड़ा नहीं जा सकता है, SIGKILL = 9, SIGSTOP = 19। और अन्य संकेत (जब अनकैप्ड) भी प्रक्रिया समाप्ति में परिणाम कर सकते हैं।

आप एक अधिक सामान्य डेमनीज फ़ंक्शन चाहते हैं, जहां आप अपने प्रोग्राम / डेमॉन के लिए एक नाम निर्दिष्ट कर सकते हैं, और अपने प्रोग्राम को चलाने के लिए एक पथ (शायद "/" या "/ tmp")। आप stderr और stdout (और संभवतः स्टड का उपयोग करके एक नियंत्रण पथ) के लिए फ़ाइल (s) प्रदान करना चाह सकते हैं।

यहाँ आवश्यक शामिल हैं:

#include <stdio.h>    //printf(3)
#include <stdlib.h>   //exit(3)
#include <unistd.h>   //fork(3), chdir(3), sysconf(3)
#include <signal.h>   //signal(3)
#include <sys/stat.h> //umask(3)
#include <syslog.h>   //syslog(3), openlog(3), closelog(3)

और यहाँ एक अधिक सामान्य कार्य है,

int
daemonize(char* name, char* path, char* outfile, char* errfile, char* infile )
{
    if(!path) { path="/"; }
    if(!name) { name="medaemon"; }
    if(!infile) { infile="/dev/null"; }
    if(!outfile) { outfile="/dev/null"; }
    if(!errfile) { errfile="/dev/null"; }
    //printf("%s %s %s %s\n",name,path,outfile,infile);
    pid_t child;
    //fork, detach from process group leader
    if( (child=fork())<0 ) { //failed fork
        fprintf(stderr,"error: failed fork\n");
        exit(EXIT_FAILURE);
    }
    if (child>0) { //parent
        exit(EXIT_SUCCESS);
    }
    if( setsid()<0 ) { //failed to become session leader
        fprintf(stderr,"error: failed setsid\n");
        exit(EXIT_FAILURE);
    }

    //catch/ignore signals
    signal(SIGCHLD,SIG_IGN);
    signal(SIGHUP,SIG_IGN);

    //fork second time
    if ( (child=fork())<0) { //failed fork
        fprintf(stderr,"error: failed fork\n");
        exit(EXIT_FAILURE);
    }
    if( child>0 ) { //parent
        exit(EXIT_SUCCESS);
    }

    //new file permissions
    umask(0);
    //change to path directory
    chdir(path);

    //Close all open file descriptors
    int fd;
    for( fd=sysconf(_SC_OPEN_MAX); fd>0; --fd )
    {
        close(fd);
    }

    //reopen stdin, stdout, stderr
    stdin=fopen(infile,"r");   //fd=0
    stdout=fopen(outfile,"w+");  //fd=1
    stderr=fopen(errfile,"w+");  //fd=2

    //open syslog
    openlog(name,LOG_PID,LOG_DAEMON);
    return(0);
}

यहां एक नमूना कार्यक्रम है, जो डेमॉन बन जाता है, चारों ओर लटका हुआ है, और फिर निकल जाता है।

int
main()
{
    int res;
    int ttl=120;
    int delay=5;
    if( (res=daemonize("mydaemon","/tmp",NULL,NULL,NULL)) != 0 ) {
        fprintf(stderr,"error: daemonize failed\n");
        exit(EXIT_FAILURE);
    }
    while( ttl>0 ) {
        //daemon code here
        syslog(LOG_NOTICE,"daemon ttl %d",ttl);
        sleep(delay);
        ttl-=delay;
    }
    syslog(LOG_NOTICE,"daemon ttl expired");
    closelog();
    return(EXIT_SUCCESS);
}

ध्यान दें कि SIG_IGN सिग्नल को पकड़ने और अनदेखा करने के लिए इंगित करता है। आप एक सिग्नल हैंडलर का निर्माण कर सकते हैं जो सिग्नल की रसीद लॉग कर सकता है, और झंडे सेट कर सकता है (जैसे कि सुंदर बंद को इंगित करने के लिए एक झंडा)।


8

daemonफ़ंक्शन का उपयोग करने का प्रयास करें :

#include <unistd.h>

int daemon(int nochdir, int noclose);

से आदमी पेज :

डेमॉन () फ़ंक्शन कंट्रोलिंग टर्मिनल से खुद को अलग करने और सिस्टम डेमॉन के रूप में पृष्ठभूमि में चलने वाले कार्यक्रमों के लिए है।

यदि नोचडिर शून्य है, डेमन () कॉलिंग की वर्तमान कार्यशील निर्देशिका को रूट निर्देशिका ("/") में बदल देता है; अन्यथा, वर्तमान कार्य निर्देशिका को अपरिवर्तित छोड़ दिया जाता है।

यदि noclose शून्य है, तो डेमन () / dev / null में मानक इनपुट, मानक आउटपुट और मानक त्रुटि को पुनर्निर्देशित करता है; अन्यथा, इन फ़ाइल विवरणों में कोई बदलाव नहीं किया गया है।


2
ध्यान दें कि daemon(7)मैनुअल डेमॉन बनाने के लिए चरणों का उल्लेख करता है और चेतावनी देता है कि: बीएसडी daemon()फ़ंक्शन का उपयोग नहीं किया जाना चाहिए, क्योंकि यह इन चरणों का केवल सबसेट लागू करता है। daemonसमारोह में पहली बार दिखाई दिया 4.4BSD और है नहीं POSIX अनुरूप
patryk.beza

2
यह भी ध्यान दें कि डेमन () का उपयोग करने के बारे में चेतावनी डेमन (7) मैन पेज के पुराने-शैली SysV अनुभाग में है । सिस्टमन के लिए डेमन () का उपयोग हतोत्साहित नहीं है।
ग्रेग मैकफेरन

7

मैं पहली आवश्यकता पर रोक सकता है "एक डेमन जिसे रोका नहीं जा सकता ..."

संभव नहीं मेरे दोस्त; हालाँकि, आप एक बेहतर उपकरण, कर्नेल मॉड्यूल के साथ इसे प्राप्त कर सकते हैं।

http://www.infoq.com/articles/inotify-linux-file-system-event-monitoring

सभी डेमों को रोका जा सकता है। कुछ दूसरों की तुलना में अधिक आसानी से बंद हो जाते हैं। यहां तक ​​कि पार्टनर के साथ एक डेमन जोड़ी पकड़ में आ जाती है, अगर पार्टनर खो जाए तो उसे रोका जा सकता है। आपको बस इसमें थोड़ी मेहनत करनी होगी।


7
मुझे लगता है कि "एक डेमन जिसे रोका नहीं जा सकता" कहकर लेखक ने वास्तव में सत्र समाप्त होने पर डेमन हमेशा पृष्ठभूमि चला रहा है।
फेसब्रो

6

यदि आपका ऐप इनमें से एक है:

{
  ".sh": "bash",
  ".py": "python",
  ".rb": "ruby",
  ".coffee" : "coffee",
  ".php": "php",
  ".pl" : "perl",
  ".js" : "node"
}

और आपको NodeJS निर्भरता पर कोई आपत्ति नहीं है और फिर NodeJS स्थापित करें और फिर:

npm install -g pm2

pm2 start yourapp.yourext --name "fred" # where .yourext is one of the above

pm2 start yourapp.yourext -i 0 --name "fred" # run your app on all cores

pm2 list

रिबूट (और डेमनीज़ pm2) पर चलने वाले सभी ऐप रखने के लिए:

pm2 startup

pm2 save

अब आप कर सकते हैं:

service pm2 stop|restart|start|status

(यह भी आसानी से आप अपने अनुप्रयोग निर्देशिका में कोड परिवर्तन के लिए देखने के लिए अनुमति देता है और एक कोड परिवर्तन होता है जब ऑटो प्रक्रिया फिर से शुरू होता है)


2
यह कुछ भी नहीं सी के साथ क्या करना है
melpomene

4
मैं सराहना करता हूं कि एक सी टैग है। हालांकि, ओपी प्रश्न में सी से संबंधित एक आवश्यकता का उल्लेख नहीं करता है। शीर्षक लिनक्स में एक दानव पैदा कर रहा है। यह जवाब संतुष्ट करता है कि।
danday74

1
ओह, तुम सही हो। इसे C टैग किया गया है, लेकिन वास्तविक आवश्यकता C ++ है (जैसा कि ओपी के कोड और जुड़े लेख द्वारा स्पष्ट किया गया है)।
melpomene

3

फोर्क () कॉल करके आपने एक चाइल्ड प्रोसेस बनाया है। यदि कांटा सफल होता है (कांटा एक गैर-शून्य पीआईडी ​​लौटाता है) तो इस प्रक्रिया से बच्चे की प्रक्रिया के भीतर निष्पादन जारी रहेगा। इस मामले में हम अभिभावक की प्रक्रिया से हटना चाहते हैं और फिर बाल प्रक्रिया में अपना काम जारी रखेंगे।

शायद यह मदद करेगा: http://www.netzmafia.de/skripten/unix/linux-daemon-howto.html


2

एक डेमॉन पृष्ठभूमि में सिर्फ एक प्रक्रिया है। यदि आप OS बूट होने पर अपना प्रोग्राम शुरू करना चाहते हैं, तो आप अपना प्रारंभ कमांड /etc/rc.d/rc.local (अन्य सभी लिपियों के बाद चलाएँ) या /etc/startup.sh में जोड़ते हैं

खिड़कियों पर, आप एक सेवा बनाते हैं, सेवा को पंजीकृत करते हैं, और फिर इसे प्रशासन -> सेवा पैनल में बूट पर स्वचालित रूप से शुरू करने के लिए सेट करते हैं।


1
धन्यवाद। तो क्या "डेमॉन" और सिर्फ एक सामान्य प्रोग्राम में कोई अंतर नहीं है? मैं नहीं चाहता कि यह आसानी से बंद हो जाए।
क्रिसम

1
नहीं, डेमॉन एक पृष्ठभूमि प्रक्रिया है। विशेष रूप से, आप एक माता-पिता से कांटा करते हैं, बच्चे की प्रक्रिया को चलाते हैं और माता-पिता को समाप्त करते हैं (ताकि कार्यक्रम में कोई टर्मिनल न हो)। कि n ओट रिले एक "डेमॉन" होना आवश्यक है: en.wikipedia.org/wiki/Daemon_(computing)
Magn3s1um

1

डेमॉन टेम्पलेट

मैंने नई शैली के डेमन के बाद एक डेमॉन टेम्प्लेट लिखा: लिंक

आप GitHub पर संपूर्ण टेम्प्लेट कोड पा सकते हैं: यहां

main.cpp

// This function will be called when the daemon receive a SIGHUP signal.
void reload() {
    LOG_INFO("Reload function called.");
}

int main(int argc, char **argv) {
    // The Daemon class is a singleton to avoid be instantiate more than once
    Daemon& daemon = Daemon::instance();
    // Set the reload function to be called in case of receiving a SIGHUP signal
    daemon.setReloadFunction(reload);
    // Daemon main loop
    int count = 0;
    while(daemon.IsRunning()) {
        LOG_DEBUG("Count: ", count++);
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
    LOG_INFO("The daemon process ended gracefully.");
}

Daemon.hpp

class Daemon {
    public:

    static Daemon& instance() {
        static Daemon instance;
        return instance;
    }

    void setReloadFunction(std::function<void()> func);

    bool IsRunning();

    private:

    std::function<void()> m_reloadFunc;
    bool m_isRunning;
    bool m_reload;

    Daemon();
    Daemon(Daemon const&) = delete;
    void operator=(Daemon const&) = delete;

    void Reload();

    static void signalHandler(int signal);
};

Daemon.cpp

Daemon::Daemon() {
    m_isRunning = true;
    m_reload = false;
    signal(SIGINT, Daemon::signalHandler);
    signal(SIGTERM, Daemon::signalHandler);
    signal(SIGHUP, Daemon::signalHandler);
}

void Daemon::setReloadFunction(std::function<void()> func) {
    m_reloadFunc = func;
}

bool Daemon::IsRunning() {
    if (m_reload) {
        m_reload = false;
        m_reloadFunc();
    }
    return m_isRunning;
}

void Daemon::signalHandler(int signal) {
    LOG_INFO("Interrup signal number [", signal,"] recived.");
    switch(signal) {
        case SIGINT:
        case SIGTERM: {
            Daemon::instance().m_isRunning = false;
            break;
        }
        case SIGHUP: {
            Daemon::instance().m_reload = true;
            break;
        }
    }
}

डेमॉन-template.service

[Unit]
Description=Simple daemon template
After=network.taget

[Service]
Type=simple
ExecStart=/usr/bin/daemon-template --conf_file /etc/daemon-template/daemon-tenplate.conf
ExecReload=/bin/kill -HUP $MAINPID
User=root
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=daemon-template

[Install]
WantedBy=multi-user.target
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.