Créer un démon sous Linux


110

Sous Linux, je souhaite ajouter un démon qui ne peut pas être arrêté et qui surveille les modifications du système de fichiers. Si des changements sont détectés, il doit écrire le chemin d'accès à la console où il a été démarré plus une nouvelle ligne.

J'ai déjà le code de changement de système de fichiers presque prêt mais je ne peux pas comprendre comment créer un démon.

Mon code vient d'ici: http://www.yolinux.com/TUTORIALS/ForkExecProcesses.html

Que faire après la fourche?

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
duplication possible de: stackoverflow.com/questions/5384168/… pour la partie daemonize, stackoverflow.com/questions/931093/… pour la surveillance du système de fichiers
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Si vous n'avez pas besoin de la conformité POSIX, vous pourriez être intéressé par l' inotifyAPI. Voir: inotify_init, inotify_add_watch, inotify_rm_watch.
patryk.beza

Réponses:


216

Sous Linux, je veux ajouter un démon qui ne peut pas être arrêté et qui surveille les modifications du système de fichiers. Si des changements sont détectés, il doit écrire le chemin d'accès à la console où il a été démarré + une nouvelle ligne.

Les démons fonctionnent en arrière-plan et (généralement ...) n'appartiennent pas à un TTY, c'est pourquoi vous ne pouvez pas utiliser stdout / stderr comme vous le souhaitez probablement. Habituellement, un démon syslog ( syslogd ) est utilisé pour consigner les messages dans les fichiers (débogage, erreur, ...).

En plus de cela, il y a quelques étapes requises pour démoniser un processus.


Si je me souviens bien, ces étapes sont:

  • bifurquer le processus parent et le laisser se terminer si la fourche a réussi. -> Le processus parent étant terminé, le processus enfant s'exécute maintenant en arrière-plan.
  • setsid - Crée une nouvelle session. Le processus appelant devient le chef de file de la nouvelle session et le chef du groupe de processus du nouveau groupe de processus. Le processus est maintenant détaché de son terminal de contrôle (CTTY).
  • Capturer les signaux - Ignorer et / ou gérer les signaux.
  • fork à nouveau et laissez le processus parent se terminer pour vous assurer que vous vous débarrassez du processus de tête de session. (Seuls les chefs de session peuvent obtenir à nouveau un ATS.)
  • chdir - Modifie le répertoire de travail du démon.
  • umask - Changez le masque de mode de fichier en fonction des besoins du démon.
  • close - Ferme tous les descripteurs de fichiers ouverts qui peuvent être hérités du processus parent.

Pour vous donner un point de départ: Regardez ce code squelette qui montre les étapes de base. Ce code peut maintenant également être forké sur GitHub: squelette de base d'un démon linux

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


  • Compilez le code: gcc -o firstdaemon daemonize.c
  • Démarrez le démon: ./firstdaemon
  • Vérifiez si tout fonctionne correctement: ps -xj | grep firstdaemon

  • La sortie doit être similaire à celle-ci:

+ ------ + ------ + ------ + ------ + ----- + ------- + ------ + ------ + ------ + ----- +
| PPID | PID | PGID | SID | TTY | TPGID | STAT | UID | TIME | CMD |
+ ------ + ------ + ------ + ------ + ----- + ------- + ------ + ------ + ------ + ----- +
| 1 | 3387 | 3386 | 3386 | ? | -1 | S | 1000 | 0:00 | ./ |
+ ------ + ------ + ------ + ------ + ----- + ------- + ------ + ------ + ------ + ----- +

Ce que vous devriez voir ici, c'est:

  • Le démon n'a pas de terminal de contrôle ( TTY =? )
  • L'ID de processus parent ( PPID ) est 1 (le processus d'initialisation)
  • Le PID! = SID ce qui signifie que notre processus n'est PAS le leader de la session
    (à cause du second fork ())
  • Parce que PID! = SID, notre processus ne peut pas reprendre le contrôle d'un TTY

Lecture du syslog:

  • Localisez votre fichier syslog. Le mien est ici:/var/log/syslog
  • Fait une: grep firstdaemon /var/log/syslog

  • La sortie doit être similaire à celle-ci:

  firstdaemon [3387]: Le premier démon a démarré.
  firstdaemon [3387]: le premier démon est terminé.


Remarque: en réalité, vous voudriez également implémenter un gestionnaire de signaux et configurer correctement la journalisation (fichiers, niveaux de journalisation ...).

Lectures complémentaires:


Ouah merci! C'est génial. Donc je dois mettre mon code dans la boucle while et c'est tout?
chrisMe

Fondamentalement, oui. Mais ce code n'est qu'un exemple. Cela dépend entièrement de ce que vous voulez réaliser en utilisant un processus démon. Assurez-vous de lire aussi cette réponse: @Edwin
Pascal Werkl

1
Au lieu du second fork(), pourquoi ne pas simplement utiliser setsid()?
Chimera

1
Notez que la sigaction()fonction fournit un mécanisme plus complet et plus fiable pour contrôler les signaux; les nouvelles applications devraient utiliser sigaction()plutôt que signal().
patryk.beza

4
Il convient de noter aux téléspectateurs que cette méthode est la «vieille» méthode. La nouvelle façon recommandée de créer un démon est d'utiliser le "nouveau démon de style" trouvé ici: 0pointer.de/public/systemd-man/daemon.html#New-Style%20Daemons ou
Starlord

30

man 7 daemondécrit comment créer un démon en détail. Ma réponse n'est qu'un extrait de ce manuel.

Il existe au moins deux types de démons:

  1. démons SysV traditionnels (à l' ancienne ),
  2. démons systemd ( nouveau style ).

Démons SysV

Si vous êtes intéressé par le démon SysV traditionnel , vous devez implémenter les étapes suivantes :

  1. Fermez tous les descripteurs de fichiers ouverts à l'exception de l' entrée standard , de la sortie et de l' erreur (c'est-à-dire les trois premiers descripteurs de fichier 0, 1, 2). Cela garantit qu'aucun descripteur de fichier transmis accidentellement ne reste dans le processus démon. Sous Linux, il est préférable de l'implémenter en itérant à travers /proc/self/fd, avec un retour d'itération du descripteur de fichier 3 à la valeur renvoyée par getrlimit()for RLIMIT_NOFILE.
  2. Réinitialisez tous les gestionnaires de signaux à leur valeur par défaut. Pour ce faire, il est préférable d'itérer les signaux disponibles jusqu'à la limite de _NSIGet de les réinitialiser SIG_DFL.
  3. Réinitialisez le masque de signal à l'aide de sigprocmask().
  4. Nettoyez le bloc d'environnement, supprimez ou réinitialisez les variables d'environnement qui pourraient avoir un impact négatif sur l'exécution du démon.
  5. Appelez fork(), pour créer un processus d'arrière-plan.
  6. Dans l'enfant, appelez setsid()pour se détacher de n'importe quel terminal et créer une session indépendante .
  7. Dans l'enfant, appelez à fork()nouveau pour vous assurer que le démon ne pourra plus jamais réacquérir un terminal.
  8. Appelez exit()le premier enfant, de sorte que seul le deuxième enfant (le processus démon réel) reste là. Cela garantit que le processus démon est re-parenté à init / PID 1, comme tous les démons devraient l'être.
  9. Dans le processus démon, connectez-vous /dev/nullà l' entrée , à la sortie et à l' erreur standard .
  10. Dans le processus démon, réinitialisez le umaskà 0, de sorte que les modes de fichiers passés à open(), mkdir()et autres contrôlent directement le mode d'accès des fichiers et répertoires créés.
  11. Dans le processus du démon, changez le répertoire courant en répertoire racine ( /), afin d'éviter que le démon empêche involontairement le démontage des points de montage.
  12. Dans le processus du démon, écrivez le PID du démon (tel que renvoyé par getpid()) dans un fichier PID, par exemple /run/foobar.pid(pour un démon hypothétique "foobar") pour vous assurer que le démon ne peut pas être démarré plus d'une fois. Cela doit être mis en œuvre sans course afin que le fichier PID ne soit mis à jour que lorsqu'il est vérifié en même temps que le PID précédemment stocké dans le fichier PID n'existe plus ou appartient à un processus étranger.
  13. Dans le processus démon, supprimez les privilèges, si possible et applicable.
  14. A partir du processus démon, informez le processus d'origine démarré que l'initialisation est terminée. Cela peut être implémenté via un canal sans nom ou un canal de communication similaire qui est créé avant le premier fork()et donc disponible dans le processus d'origine et le processus démon.
  15. Appelez exit()le processus d'origine. Le processus qui a appelé le démon doit pouvoir compter sur le fait que cela exit()se produit une fois l' initialisation terminée et tous les canaux de communication externes sont établis et accessibles.

Notez cet avertissement:

La daemon()fonction BSD ne doit pas être utilisée, car elle implémente uniquement un sous - ensemble de ces étapes.

Un démon qui doit assurer la compatibilité avec les systèmes SysV devrait implémenter le schéma indiqué ci-dessus. Cependant, il est recommandé de rendre ce comportement facultatif et configurable via un argument de ligne de commande pour faciliter le débogage ainsi que pour simplifier l'intégration dans les systèmes utilisant systemd.

Notez que ce daemon()n'est pas conforme à POSIX .


Démons de style nouveau

Pour les démons de nouveau style, les étapes suivantes sont recommandées:

  1. Si SIGTERMest reçu, arrêtez le démon et quittez proprement.
  2. Si SIGHUPest reçu, rechargez les fichiers de configuration, si cela s'applique.
  3. Fournissez un code de sortie correct du processus démon principal, car il est utilisé par le système d'initialisation pour détecter les erreurs et les problèmes de service. Il est recommandé de suivre le schéma de code de sortie tel que défini dans les recommandations LSB pour les scripts d'initialisation SysV .
  4. Si possible et applicable, exposez l'interface de contrôle du démon via le système D-Bus IPC et saisissez un nom de bus comme dernière étape de l'initialisation.
  5. Pour l'intégration dans systemd, fournissez un fichier d' unité .service contenant des informations sur le démarrage, l'arrêt et la maintenance du démon. Voir pour plus de détails.systemd.service(5)
  6. Autant que possible, comptez sur les fonctionnalités du système init pour limiter l'accès du démon aux fichiers, services et autres ressources, c'est-à-dire dans le cas de systemd, comptez sur le contrôle de limite de ressources de systemd au lieu d'implémenter le vôtre, comptez sur l' abandon des privilèges de systemd code au lieu de l'implémenter dans le démon, et similaire. Voir systemd.exec(5)pour les commandes disponibles.
  7. Si D-Bus est utilisé, rendez votre démon activable en fournissant un fichier de configuration d' activation du service D-Bus . Cela présente de multiples avantages: votre démon peut être démarré paresseusement à la demande; il peut être démarré en parallèle avec d'autres démons qui l'exigent - ce qui maximise la parallélisation et la vitesse de démarrage ; votre démon peut être redémarré en cas d'échec sans perdre aucune demande de bus, car le bus met en file d'attente les demandes de services activables. Voir ci - dessous pour plus de détails.
  8. Si votre démon fournit des services à d'autres processus locaux ou clients distants via une socket, il doit être rendu activable par socket en suivant le schéma indiqué ci-dessous . Comme l'activation D-Bus, cela permet le démarrage à la demande des services et permet une meilleure parallélisation du démarrage des services. De plus, pour les protocoles sans état (tels que syslog, DNS), un démon implémentant l'activation basée sur socket peut être redémarré sans perdre une seule requête. Voir ci - dessous pour plus de détails.
  9. Le cas échéant, un démon doit informer le système d'initialisation de l'achèvement du démarrage ou des mises à jour d'état via l' sd_notify(3)interface.
  10. Au lieu d'utiliser l' syslog()appel pour se connecter directement au service syslog du système, un démon de nouveau style peut choisir de simplement se connecter à l'erreur standard via fprintf(), qui est ensuite transmise à syslog par le système init. Si des niveaux de journalisation sont nécessaires, ceux-ci peuvent être encodés en préfixant les lignes de journal individuelles avec des chaînes comme "<4>" (pour le niveau de journal 4 "WARNING" dans le schéma de priorité syslog), en suivant un style similaire au système de printk()niveau du noyau Linux . Pour plus de détails, voir sd-daemon(3)et systemd.exec(5).

Pour en savoir plus, lisez le tout man 7 daemon.


11

Vous ne pouvez pas créer un processus sous Linux qui ne peut pas être tué. L'utilisateur root (uid = 0) peut envoyer un signal à un processus, et il y a deux signaux qui ne peuvent pas être capturés, SIGKILL = 9, SIGSTOP = 19. Et d'autres signaux (lorsqu'ils ne sont pas interceptés) peuvent également entraîner l'arrêt du processus.

Vous voudrez peut-être une fonction de démonisation plus générale, où vous pouvez spécifier un nom pour votre programme / démon, et un chemin pour exécuter votre programme (peut-être "/" ou "/ tmp"). Vous pouvez également fournir des fichiers pour stderr et stdout (et éventuellement un chemin de contrôle en utilisant stdin).

Voici les éléments nécessaires:

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

Et voici une fonction plus générale,

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

Voici un exemple de programme, qui devient un démon, traîne, puis part.

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

Notez que SIG_IGN indique d'attraper et d'ignorer le signal. Vous pouvez créer un gestionnaire de signaux qui peut enregistrer la réception du signal et définir des indicateurs (tels qu'un indicateur pour indiquer un arrêt normal).


8

Essayez d'utiliser la daemonfonction:

#include <unistd.h>

int daemon(int nochdir, int noclose);

Depuis la page de manuel :

La fonction daemon () est destinée aux programmes souhaitant se détacher du terminal de contrôle et s'exécuter en arrière-plan en tant que démons système.

Si nochdir vaut zéro, daemon () remplace le répertoire de travail actuel du processus appelant par le répertoire racine ("/"); sinon, le répertoire de travail actuel reste inchangé.

Si noclose vaut zéro, daemon () redirige l'entrée standard, la sortie standard et l'erreur standard vers / dev / null; sinon, aucune modification n'est apportée à ces descripteurs de fichier.


2
Notez que le daemon(7)manuel mentionne les étapes de création du démon et avertit que: La daemon()fonction BSD ne doit pas être utilisée, car elle implémente seulement un sous-ensemble de ces étapes. daemonLa fonction est apparue pour la première fois dans 4.4BSD et n'est pas compatible POSIX .
patryk.beza

2
Notez également que l'avertissement concernant l'utilisation de daemon () se trouve dans la section SysV à l'ancienne de la page de manuel de daemon (7) . L'utilisation de daemon () n'est pas déconseillée pour systemd.
Greg McPherran

7

Je peux m'arrêter à la première exigence "Un démon qui ne peut pas être arrêté ..."

Pas possible mon ami; cependant, vous pouvez obtenir la même chose avec un bien meilleur outil, un module de noyau.

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

Tous les démons peuvent être arrêtés. Certains sont plus facilement arrêtés que d'autres. Même une paire de démons avec le partenaire en attente, réapparaissant en cas de perte, peut être arrêtée. Vous devez juste travailler un peu plus dur.


7
Je pense qu'en disant "Un démon qui ne peut pas être arrêté", l'auteur veut dire en fait que le démon est toujours en arrière-plan lorsque la session est terminée.
FaceBro

6

Si votre application fait partie des:

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

et cela ne vous dérange pas une dépendance NodeJS, puis installez NodeJS et ensuite:

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

Pour garder toutes les applications en cours d'exécution au redémarrage (et démoniser pm2):

pm2 startup

pm2 save

Maintenant vous pouvez:

service pm2 stop|restart|start|status

(vous permet également de surveiller facilement les changements de code dans votre répertoire d'applications et de redémarrer automatiquement le processus d'application lorsqu'un changement de code se produit)


2
Cela n'a rien à voir avec C.
melpomene

4
J'apprécie qu'il y ait une balise C. Cependant, OP ne mentionne pas d'exigence concernant C dans la question. Le titre crée un démon sous Linux. Cette réponse satisfait cela.
danday74

1
Oh, tu as raison. Il est étiqueté C, mais l'exigence réelle est C ++ (comme en témoignent le code d'OP et l'article lié).
melpomene

3

En appelant fork (), vous avez créé un processus enfant. Si le fork réussit (fork a renvoyé un PID différent de zéro), l'exécution se poursuivra à partir de ce point à partir du processus enfant. Dans ce cas, nous voulons quitter gracieusement le processus parent, puis continuer notre travail dans le processus enfant.

Peut-être que cela aidera: http://www.netzmafia.de/skripten/unix/linux-daemon-howto.html


2

Un démon n'est qu'un processus en arrière-plan. Si vous souhaitez démarrer votre programme au démarrage du système d'exploitation, sous Linux, vous ajoutez votre commande de démarrage à /etc/rc.d/rc.local (exécutée après tous les autres scripts) ou /etc/startup.sh

Sous Windows, vous créez un service, enregistrez le service, puis configurez-le pour qu'il démarre automatiquement au démarrage dans l'administration -> panneau des services.


1
Merci. Alors n'y a-t-il aucune différence entre un "démon" et juste un programme normal? Je ne veux pas qu'il se ferme facilement.
chrisMe

1
Non, un démon n'est qu'un processus d'arrière-plan. Plus précisément, vous dérivez d'un parent, exécutez le processus enfant et terminez le parent (afin qu'il n'y ait pas d'accès de terminal au programme). ce n'est pas vraiment nécessaire pour être un "démon": en.wikipedia.org/wiki/Daemon_(computing)
Magn3s1um

1

Modèle de démon

J'ai écrit un modèle de démon en suivant le démon de nouveau style: lien

Vous pouvez trouver l'intégralité du code du modèle sur GitHub: ici

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;
        }
    }
}

daemon-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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.