লিনাক্সে ডেমন তৈরি করা হচ্ছে


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

1
সম্ভাব্য সদৃশ: stackoverflow.com/questions/5384168/... daemonize অংশ জন্য, stackoverflow.com/questions/931093/... ফাইলসিস্টেম ঘড়ির জন্য
সিরো Santilli郝海东冠状病六四事件法轮功

আপনার যদি পসিক্স সম্মতির প্রয়োজন না হয় তবে আপনি এপিআইতে আগ্রহী হতে পারেন inotify। দেখুন: inotify_init, inotify_add_watch, inotify_rm_watch
patryk.beza

উত্তর:


216

লিনাক্সে আমি এমন একটি ডেমন যুক্ত করতে চাই যা থামানো যায় না এবং যা ফাইল সিস্টেমের পরিবর্তনের উপর নজর রাখে। যদি কোনও পরিবর্তন শনাক্ত করা যায় তবে এটি কনসোলে যেখানে এটি শুরু হয়েছিল + একটি নতুন লাইন লিখতে হবে।

ডেমনগুলি ব্যাকগ্রাউন্ডে কাজ করে এবং (সাধারণত ...) কোনও টিটিওয়াইয়ের অন্তর্ভুক্ত না যে কারণে আপনি সম্ভবত যেভাবে স্টাডাউট / স্টাডার ব্যবহার করতে পারবেন না। সাধারণত একটি সিসলগ ডেমন ( সিসলগড) ফাইলগুলিতে বার্তা লগ করার জন্য ) ব্যবহৃত হয় (ডিবাগ, ত্রুটি, ...)।

তা ছাড়াও কয়েকটি প্রয়োজনীয় পদক্ষেপ রয়েছে একটি প্রক্রিয়া ডিমনাইজ করার জন্য ।


যদি আমি সঠিকভাবে মনে করি তবে এই পদক্ষেপগুলি হ'ল:

  • কাঁটাচামচমূল প্রক্রিয়াটি এবং সফল হলে এটি বন্ধ করতে দিন। -> পিতামাতার প্রক্রিয়াটি বন্ধ হয়ে যাওয়ার কারণে, শিশু প্রক্রিয়া এখন পটভূমিতে চলে।
  • setsid - একটি নতুন সেশন তৈরি করুন। কলিং প্রক্রিয়া নতুন সেশনের নেতা এবং নতুন প্রক্রিয়া গ্রুপের প্রক্রিয়া গ্রুপের নেতা হয়। প্রক্রিয়াটি এখন তার নিয়ন্ত্রণকারী টার্মিনাল (সিটিটিওয়াই) থেকে আলাদা করা হয়েছে।
  • সিগন্যাল ধরুন - উপেক্ষা করুন এবং / অথবা সিগন্যালগুলি হ্যান্ডেল করুন।
  • আবার কাঁটাচামচ & আপনি সেশন নেতৃস্থানীয় প্রক্রিয়া থেকে মুক্তি পেয়েছেন তা নিশ্চিত করতে পিতামাতার প্রক্রিয়াটি শেষ হতে দিন। (কেবল অধিবেশন নেতারা আবারও টিটিওয়াই পেতে পারেন))
  • chdir - ডেমনের কর্ম ডিরেক্টরিটি পরিবর্তন করুন।
  • umask - ডেমনের প্রয়োজন অনুসারে ফাইল মোড মাস্ক পরিবর্তন করুন।
  • বন্ধ - পিতা-মাতার প্রক্রিয়া থেকে উত্তরাধিকারসূত্রে প্রাপ্ত সমস্ত উন্মুক্ত ফাইল বর্ণনাকারী বন্ধ করুন।

আপনাকে একটি সূচনা পয়েন্ট দেওয়ার জন্য: এই কঙ্কাল কোডটি দেখুন যা প্রাথমিক পদক্ষেপগুলি দেখায়। এই কোডটি এখন গিটহাবের উপরেও তৈরি করা যেতে পারে: একটি লিনাক্স ডেমনের বেসিক কঙ্কাল

/*
 * 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

  • আউটপুট এটির মতো হওয়া উচিত:

+ + ------ + + ------ + + ------ + + ------ + + ----- + + ------- + + ------ + + ------ + + ------ + + ----- + +
| পিপিআইডি | পিআইডি | পিজিআইডি | এসআইডি | টিটিওয়াই | টিপিজিআইডি | স্ট্যাট | ইউআইডি | সময় | সিএমডি |
+ + ------ + + ------ + + ------ + + ------ + + ----- + + ------- + + ------ + + ------ + + ------ + + ----- + +
| 1 | 3387 | 3386 | 3386 | ? | -1 | এস | 1000 | 0:00 | ./ |
+ + ------ + + ------ + + ------ + + ------ + + ----- + + ------- + + ------ + + ------ + + ------ + + ----- + +

আপনার এখানে যা দেখা উচিত তা হ'ল:

  • ডিমনটির কোনও নিয়ন্ত্রণকারী টার্মিনাল নেই ( টিটিওয়াই =? )
  • প্যারেন্ট প্রসেস আইডি ( পিপিআইডি ) হ'ল 1 (আরম্ভ প্রক্রিয়া)
  • PID,! = জন্য SID যার মানে আমাদের প্রক্রিয়া করতে অধিবেশন নেতা
    (দ্বিতীয় কাঁটাচামচ কারণে ())
  • কারণ পিআইডি! = এসআইডি আমাদের প্রক্রিয়া আবার কোনও টিটিওয়াইয়ের নিয়ন্ত্রণ নিতে পারে না

সিসলগ পড়া:

  • আপনার সিসলগ ফাইলটি সন্ধান করুন। খনি এখানে:/var/log/syslog
  • একটি করুন: grep firstdaemon /var/log/syslog

  • আউটপুট এটির মতো হওয়া উচিত:

  ফার্স্টডেমন [3387]: প্রথম ডেমন শুরু হয়েছে।
  ফার্স্টডেমন [৩৩ ]87]: প্রথম ডিমন সমাপ্ত।


একটি নোট: বাস্তবে আপনি একটি সিগন্যাল হ্যান্ডলার বাস্তবায়ন করতে এবং লগিং সঠিকভাবে সেট আপ করতে চাইবেন (ফাইল, লগ স্তর ...))

আরও পড়া:


ওহ ধন্যবাদ! দারুণ. সুতরাং আমি আমার কোডটি লুপের মধ্যে রেখে তা চালিয়ে যাব?
ক্রিসমেম

মূলত, হ্যাঁ তবে এই কোডটি একটি উদাহরণ মাত্র। এটি সম্পূর্ণরূপে ডেমন প্রক্রিয়াটি ব্যবহার করে আপনি কী অর্জন করতে চান তার উপর নির্ভর করে । এই উত্তরটিও
পাস্কাল ওয়ার্কল

1
দ্বিতীয়টির পরিবর্তে fork(), কেন কেবল ব্যবহার setsid()করবেন না ?
চিমেরা

1
উল্লেখ্য যে ফাংশন সংকেত নিয়ন্ত্রণ জন্য একটা আরো সুসংহত এবং নির্ভরযোগ্য প্রক্রিয়া প্রদান করে; পরিবর্তে নতুন অ্যাপ্লিকেশন ব্যবহার করা উচিত sigaction()sigaction()signal()
patryk.beza

4
দর্শকদের জন্য লক্ষ্য করা উচিত যে এই পদ্ধতিটি "পুরানো" উপায়। : একটি ডেমন তৈরি করতে নতুন প্রস্তাবিত উপায় "নতুন শৈলী ডেমন" এখানে পাওয়া সাথে আছেন 0pointer.de/public/systemd-man/daemon.html#New-Style%20Daemons বা
Starlord

30

man 7 daemonকীভাবে দুর্দান্তভাবে ডেমন তৈরি করা যায় তা বর্ণনা করে। আমার উত্তরটি এই ম্যানুয়াল থেকে কেবল উদ্ধৃত হয়েছে।

কমপক্ষে দুই ধরণের ডেমন রয়েছে:

  1. traditional তিহ্যবাহী SYS ডিমন ( পুরানো শৈলী ),
  2. সিস্টেমড ডেমন ( নতুন স্টাইল )।

এসআইএসভি ডেমনস

আপনি যদি traditional তিহ্যবাহী সিএসভি ডেমনটিতে আগ্রহী হন তবে আপনার নিম্নলিখিত পদক্ষেপগুলি প্রয়োগ করতে হবে :

  1. স্ট্যান্ডার্ড ইনপুট , আউটপুট এবং ত্রুটি (যেমন প্রথম তিনটি ফাইল বর্ণনাকারী 0, 1, 2) ব্যতীত সমস্ত ওপেন ফাইল বর্ণনাকারী বন্ধ করুন । এটি নিশ্চিত করে যে কোনও দুর্ঘটনাক্রমে পাস করা ফাইল বিবরণকারী ডেমন প্রক্রিয়াতে প্রায় না থাকে s লিনাক্স, এই শ্রেষ্ঠ মাধ্যমে iterating দ্বারা বাস্তবায়িত হয় /proc/self/fd, দ্বারা ফিরে মান ফাইল বর্ণনাকারী 3 থেকে iterating একটি ফলব্যাক সঙ্গে getrlimit()জন্য RLIMIT_NOFILE
  2. সমস্ত সিগন্যাল হ্যান্ডলারকে তাদের ডিফল্টে পুনরায় সেট করুন । এটি সীমাবদ্ধতার সীমা অবধি উপলব্ধ সিগন্যালের মাধ্যমে পুনরাবৃত্তি করে _NSIGএবং সেগুলিতে পুনরায় সেট করার মাধ্যমে এটি করা ভাল SIG_DFL
  3. সিগন্যাল মাস্ক ব্যবহার করে পুনরায় সেট করুন sigprocmask()
  4. পরিবেশ ব্লককে স্যানিটাইজ করুন, পরিবেশের ভেরিয়েবলগুলি সরিয়ে ফেলা বা পুনরায় সেট করা যা ডেমন রানটাইমকে নেতিবাচকভাবে প্রভাবিত করতে পারে।
  5. কল করুন fork(), একটি পটভূমি প্রক্রিয়া তৈরি করতে।
  6. সন্তানের মধ্যে, setsid()কোনও টার্মিনাল থেকে বিচ্ছিন্ন হওয়ার জন্য এবং একটি স্বাধীন সেশন তৈরি করার জন্য কল করুন
  7. সন্তানের মধ্যে, fork()ডেমন আবার কখনও টার্মিনাল পুনরায় অর্জন করতে না পারে তা নিশ্চিত করার জন্য, আবার কল করুন ।
  8. exit()প্রথম সন্তানের দিকে কল করুন , যাতে কেবল দ্বিতীয় সন্তানের (প্রকৃত ডেমন প্রক্রিয়া) চারপাশে থাকে। এটি নিশ্চিত করে যে ডিমন প্রক্রিয়াটি আরম্ভ / পিআইডি 1 তে পুনরায় প্যারেন্টেড হয়, যেমন সমস্ত ডিমনগুলি হওয়া উচিত।
  9. ডেমন প্রক্রিয়াতে, /dev/nullস্ট্যান্ডার্ড ইনপুট , আউটপুট এবং ত্রুটির সাথে সংযুক্ত করুন
  10. ডেমন প্রক্রিয়ায়, রিসেট umask0 যাতে ফাইল মোড পাস, open(), mkdir()এবং সরাসরি নির্মিত ফাইল ও ডিরেক্টরিগুলি অ্যাক্সেস মোড নিয়ন্ত্রণ তাদৃশ।
  11. ডেমন প্রক্রিয়াতে, চলমান ডিরেক্টরিটি রুট ডিরেক্টরিতে ( ) পরিবর্তন করুন /, যাতে ডিমনটি স্বেচ্ছায় মাউন্ট পয়েন্টগুলি আনমাউন্ট থেকে আটকাতে পারে।
  12. ডিমন প্রক্রিয়াতে, ডিমন পিআইডি লিখুন (হিসাবে প্রত্যাবর্তিত getpid()) একটি পিআইডি ফাইলে লিখুন, উদাহরণস্বরূপ /run/foobar.pid(হাইপোথেটিকাল ডিমন "ফুবার" এর জন্য) যাতে ডিমনটি একবারের বেশি শুরু করা যায় না তা নিশ্চিত করে। এটি অবশ্যই রেস-মুক্ত ফ্যাশনে প্রয়োগ করা উচিত যাতে পিআইডি ফাইলটি কেবলমাত্র তখনই আপডেট হয় যখন এটি যাচাই করা হয় একই সময়ে পিআইডি ফাইলটিতে থাকা পিআইডি আর উপস্থিত থাকে না বা এটি কোনও বিদেশী প্রক্রিয়ার সাথে সম্পর্কিত।
  13. ডেমন প্রক্রিয়াতে, যদি সম্ভব হয় এবং প্রযোজ্য তবে সুবিধাগুলি বাদ দিন।
  14. ডেমন প্রক্রিয়া থেকে, প্রাথমিক প্রক্রিয়াটি শুরু করে সূচনা করুন যে ইনিশিয়েশন সম্পূর্ণ হয়েছে। এটি একটি নামবিহীন পাইপ বা অনুরূপ যোগাযোগ চ্যানেলের মাধ্যমে প্রয়োগ করা যেতে পারে যা প্রথমের আগে তৈরি হয়েছিল fork()এবং তাই মূল এবং ডেমন প্রক্রিয়া উভয় ক্ষেত্রেই উপলব্ধ।
  15. exit()আসল প্রক্রিয়াতে কল করুন । ডিমনটিকে অনুরোধ করা প্রক্রিয়াটি প্রাথমিকভাবে সম্পূর্ণ exit()হওয়ার পরে এবং সমস্ত বাহ্যিক যোগাযোগের চ্যানেলগুলি প্রতিষ্ঠিত এবং অ্যাক্সেসযোগ্য হওয়ার পরে এটির উপর নির্ভর করতে সক্ষম হতে হবে ।

এই সতর্কতা নোট করুন:

BSD daemon()ফাংশনটি ব্যবহার করা উচিত নয় , কারণ এটি এই পদক্ষেপগুলির কেবলমাত্র একটি উপসেট প্রয়োগ করে ।

একটি ডেমন যা SysV সিস্টেমের সাথে সামঞ্জস্যতা সরবরাহ করতে হবে তার উপরে বর্ণিত স্কিমটি প্রয়োগ করা উচিত। তবে, ডিবাগিং সহজ করতে পাশাপাশি সিস্টেমড ব্যবহার করে সিস্টেমে সংহতকরণকে সহজ করার জন্য কমান্ড লাইন আর্গুমেন্টের মাধ্যমে এই আচরণটি optionচ্ছিক এবং কনফিগারযোগ্য করার পরামর্শ দেওয়া হয়।

লক্ষ্য করুন daemon()নয় POSIX অনুবর্তী।


নতুন-স্টাইল ডেমোনস

নতুন স্টাইলের ডেমনগুলির জন্য নিম্নলিখিত পদক্ষেপগুলি সুপারিশ করা হয়:

  1. যদি SIGTERMতা পাওয়া যায় তবে ডেমনটি বন্ধ করে পরিষ্কারভাবে প্রস্থান করুন।
  2. যদি SIGHUPএটি প্রাপ্ত হয় তবে কনফিগারেশন ফাইলগুলি পুনরায় লোড করুন, যদি এটি প্রয়োগ হয়।
  3. মূল ডেমন প্রক্রিয়া থেকে একটি সঠিক প্রস্থান কোড সরবরাহ করুন, কারণ এটি ত্রুটি সিস্টেমটি পরিষেবা ত্রুটি এবং সমস্যা সনাক্ত করতে ব্যবহার করে। এসআইএসভি থ্রি স্ক্রিপ্টগুলির জন্য এলএসবি সুপারিশ অনুসারে প্রস্থান কোড স্কিমটি অনুসরণ করা বাঞ্ছনীয়
  4. যদি সম্ভব হয় এবং প্রযোজ্য হয়, ডি-বাস আইপিসি সিস্টেমের মাধ্যমে ডেমনটির নিয়ন্ত্রণ ইন্টারফেসটি প্রকাশ করুন এবং আরম্ভের শেষ ধাপ হিসাবে একটি বাসের নাম ধরুন।
  5. সিস্টেমেডে সংহতকরণের জন্য, একটি। সেবার্ট ইউনিট ফাইল সরবরাহ করুন যা ডেমোন শুরু করা, থামানো এবং রক্ষণাবেক্ষণ সম্পর্কে তথ্য বহন করে। দেখুন systemd.service(5)বিস্তারিত জানার জন্য।
  6. যতটা সম্ভব, ডিমানের অ্যাক্সেস ফাইল, পরিষেবা এবং অন্যান্য সংস্থানগুলিতে সীমাবদ্ধ করার জন্য init সিস্টেমের কার্যকারিতার উপর নির্ভর করুন, যেমন সিস্টেমেড ক্ষেত্রে আপনার নিজস্ব প্রয়োগের পরিবর্তে সিস্টেমেড রিসোর্স সীমাবদ্ধতা নিয়ন্ত্রণের উপর নির্ভর করুন, সিস্টেমডের সুবিধাগুলি ছাড়ার উপর নির্ভর করুন ডেমনে এটি প্রয়োগের পরিবর্তে কোড এবং অন্যান্য। systemd.exec(5)উপলব্ধ নিয়ন্ত্রণগুলি দেখুন See
  7. তাহলে ডিকপ ব্যবহার করা হয়, আপনার ডেমন একটি ডিকপ সেবা অ্যাক্টিভেশন সরবরাহ দ্বারা বাস activatable করা কনফিগারেশন ফাইল । এর একাধিক সুবিধাগুলি রয়েছে: আপনার ডেমনটি অলসভাবে চাহিদা অনুযায়ী শুরু করা যেতে পারে; এটি অন্যান্য ডেমোনগুলির সমান্তরালে এটির প্রয়োজন হতে শুরু করা যেতে পারে - যা সমান্তরালকরণ এবং বুট-আপ গতিকে সর্বাধিক করে তোলে ; অ্যাক্টিভেটেবল সার্ভিসের জন্য বাসের সারিগুলির অনুরোধ হওয়ায় কোনও বাসের অনুরোধ না হারিয়ে ব্যর্থতায় আপনার ডেমন পুনরায় চালু করা যেতে পারে। বিস্তারিত জানার জন্য নীচে দেখুন ।
  8. যদি আপনার ডেমনটি সকেটের মাধ্যমে অন্য স্থানীয় প্রক্রিয়াগুলি বা দূরবর্তী ক্লায়েন্টগুলিকে পরিষেবা সরবরাহ করে, তবে স্কিমটি নীচের দিকে নির্দেশিত অনুসারে এটি সকেট-অ্যাক্টিভিয়েটেবল করা উচিত । ডি-বাস অ্যাক্টিভেশন-এর মতো এটিও অন-ডিমান্ড পরিষেবাগুলি শুরু করার পাশাপাশি পরিষেবা স্টার্ট-আপের উন্নত সমান্তরালকরণের অনুমতি দেয়। এছাড়াও, স্টেট-কম প্রোটোকলগুলির (যেমন সিসলগ, ডিএনএস) জন্য, কোনও এক অনুরোধ না হারিয়ে ডেমোন প্রয়োগকারী সকেট-ভিত্তিক অ্যাক্টিভেশন পুনরায় চালু করা যেতে পারে। বিস্তারিত জানার জন্য নীচে দেখুন ।
  9. প্রযোজ্য ক্ষেত্রে, ডিমনকে sd_notify(3)ইন্টারফেসের মাধ্যমে সূচনা সমাপ্তি বা স্থিতির আপডেট সম্পর্কে init সিস্টেমকে অবহিত করা উচিত ।
  10. syslog()সরাসরি সিস্টেম সিসলোগ পরিষেবায় লগ করার জন্য কলটি ব্যবহার করার পরিবর্তে , একটি নতুন ধাঁচের ডিমন সহজেই স্ট্যান্ডার্ড ত্রুটির মাধ্যমে লগ করতে পছন্দ করতে পারে fprintf(), যা পরে init সিস্টেম দ্বারা সিসলগে ফরোয়ার্ড করা হয়। লগ স্তরগুলি প্রয়োজনীয় হলে লিনাক্স কার্নেলের printk()স্তর সিস্টেমের অনুরূপ স্টাইল অনুসরণ করে "<4>" (সিসলোগ অগ্রাধিকার স্কিমের লগ স্তর 4 "সতর্কতা" এর জন্য) স্ট্রিংগুলির সাথে পৃথক লগ লাইনগুলিকে উপস্থাপন করে এগুলি এনকোড করা যেতে পারে । বিশদ জন্য, দেখুন sd-daemon(3)এবং systemd.exec(5)

আরও শিখতে পুরো পড়ুন man 7 daemon


11

আপনি লিনাক্সে এমন একটি প্রক্রিয়া তৈরি করতে পারবেন না যা হত্যা করা যায় না। মূল ব্যবহারকারী (uid = 0) কোনও প্রক্রিয়াতে একটি সংকেত প্রেরণ করতে পারে এবং দুটি সিগন্যাল রয়েছে যা ধরা যায় না, SIGKILL = 9, SIGSTOP = 19। এবং অন্যান্য সিগন্যালগুলি (যখন অপরিবর্তিত থাকে) এর ফলে প্রক্রিয়াটি সমাপ্ত হতে পারে।

আপনি আরও সাধারণ ডিমনাইজেশন ফাংশন পেতে পারেন, যেখানে আপনি আপনার প্রোগ্রাম / ডেমনটির জন্য একটি নাম এবং আপনার প্রোগ্রামটি চালানোর জন্য একটি পথ নির্দিষ্ট করতে পারেন (সম্ভবত "/" বা "/ tmp")। আপনি স্ট্ডার এবং স্টডআউট (এবং সম্ভবত স্টিডিন ব্যবহার করে একটি নিয়ন্ত্রণ পাথ) এর জন্য ফাইল (গুলি) সরবরাহ করতে চাইতে পারেন।

এখানে প্রয়োজনীয় অন্তর্ভুক্ত রয়েছে:

#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);

থেকে man পৃষ্ঠা :

ডেমন () ফাংশনটি প্রোগ্রামিংগুলির জন্য যা নিজেকে নিয়ন্ত্রণকারী টার্মিনাল থেকে বিচ্ছিন্ন করতে এবং সিস্টেম ডিমন হিসাবে পটভূমিতে চালাতে চায়।

নোচডির শূন্য হলে ডিমন () কলিং প্রসেসের বর্তমান কার্য ডিরেক্টরিকে মূল ডিরেক্টরিতে ("/") পরিবর্তন করে; অন্যথায়, বর্তমান ওয়ার্কিং ডিরেক্টরিটি অপরিবর্তিত রয়েছে।

যদি নোক্লোজ শূন্য হয়, ডেমন () স্ট্যান্ডার্ড ইনপুট, স্ট্যান্ডার্ড আউটপুট এবং স্ট্যান্ডার্ড ত্রুটিটিকে / dev / নাল; অন্যথায়, এই ফাইল বর্ণনাকারীদের কোনও পরিবর্তন করা হয় না।


2
নোট করুন যে daemon(7)ম্যানুয়ালটি ডেমন তৈরি করার পদক্ষেপের উল্লেখ করে এবং সতর্ক করে যে: BSD 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"
}

এবং আপনি কোনও নোডজেএস নির্ভরতা মনে করবেন না তারপরে নোডজেএস এবং তারপরে ইনস্টল করুন:

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

সমস্ত অ্যাপ্লিকেশনগুলিকে পুনরায় বুটে চালিয়ে যেতে (এবং ডিমনাইজ পিএম 2) চালিয়ে যেতে:

pm2 startup

pm2 save

এখন তুমি পার:

service pm2 stop|restart|start|status

(এছাড়াও সহজেই আপনাকে আপনার অ্যাপ্লিকেশন ডিরেক্টরিতে কোড পরিবর্তনগুলি দেখার অনুমতি দেয় এবং কোনও কোড পরিবর্তন ঘটে গেলে অ্যাপ প্রক্রিয়াটি স্বয়ংক্রিয়ভাবে পুনঃসূচনা করতে দেয়)


2
সি এর সাথে এর কোনও
যোগসূত্র নেই

4
আমি প্রশংসা করি একটি সি ট্যাগ আছে। তবে ওপিতে প্রশ্নে সি সংক্রান্ত একটি প্রয়োজনীয়তার কথা উল্লেখ করা হয়নি। শিরোনামটি লিনাক্সে একটি রাক্ষস তৈরি করছে। এই উত্তর যে সন্তুষ্ট।
danday74

1
ওহ আপনি ঠিক. এটি সি ট্যাগ করা হয়েছে, তবে আসল প্রয়োজনীয়তা সি ++ (ওপির কোড এবং লিঙ্কযুক্ত নিবন্ধ দ্বারা প্রমাণিত)।
মেলপোমেন

3

কাঁটাচামচ () কল করে আপনি একটি শিশু প্রক্রিয়া তৈরি করেছেন। যদি কাঁটাচামচ সফল হয় (কাঁটাচামচ একটি শূন্য পিআইডি ফিরিয়ে দিয়েছে) কার্যকর করা শিশু প্রক্রিয়া থেকেই এই পয়েন্ট থেকে চালানো হবে। এক্ষেত্রে আমরা অভিভাবক প্রক্রিয়াটি করুণভাবে প্রস্থান করতে এবং তারপরে শিশু প্রক্রিয়াতে আমাদের কাজ চালিয়ে যেতে চাই।

সম্ভবত এটি সহায়তা করবে: http://www.netzmafia.de/skripten/unix/linux-daemon-howto.html


2

ডেমন পটভূমিতে কেবল একটি প্রক্রিয়া। লিনাক্সে ওএস বুট করার পরে আপনি যদি আপনার প্রোগ্রামটি শুরু করতে চান তবে আপনি আপনার প্রারম্ভকালীন কমান্ডটি /etc/rc.d/rc.local (অন্যান্য সমস্ত স্ক্রিপ্টের পরে চালানো) বা /etc/startup.sh এ যুক্ত করুন

উইন্ডোজগুলিতে, আপনি একটি পরিষেবা তৈরি করেন, পরিষেবাটি নিবন্ধভুক্ত করেন এবং তারপরে প্রশাসনের বুট-> পরিষেবাদি প্যানেলে স্বয়ংক্রিয়ভাবে শুরু করতে সেট করুন।


1
ধন্যবাদ। সুতরাং "ডিমন" এবং একটি সাধারণ প্রোগ্রামমের মধ্যে কোনও পার্থক্য নেই? আমি চাই না এটি সহজে বন্ধ হয়ে যায়।
ক্রিসমিস

1
না, একটি ডেমন কেবল একটি পটভূমি প্রক্রিয়া। আরও সুনির্দিষ্টভাবে, আপনি কোনও পিতামাতার কাছ থেকে কাঁটাচামচ করেন, সন্তানের প্রক্রিয়া চালান এবং পিতামাতাকে সমাপ্ত করবেন (যাতে প্রোগ্রামটিতে টার্মিনাল অ্যাক্সেস না থাকে)। এটি "ডিমন" হলেও এটি অপেক্ষাকৃত প্রয়োজনীয়: en.wikedia.org/wiki/Deemon_( কমপিউটিং )
Magn3s1um

1

ডেমন টেম্পলেট

আমি নতুন স্টাইলের ডেমন: লিঙ্কটি অনুসরণ করে একটি ডেমন টেম্পলেট লিখেছি

আপনি গিটহাবে পুরো টেম্পলেট কোডটি সন্ধান করতে পারেন: এখানে

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
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.