web-dev-qa-db-fra.com

L'appel au démon dans un script /etc/init.d est en cours de blocage

J'ai un script Perl que je veux démoniser. Fondamentalement, ce script Perl lit un répertoire toutes les 30 secondes, lit les fichiers qu’il trouve et traite les données. Pour simplifier, considérez le script Perl suivant (appelé synpipe_server, il existe un lien symbolique de ce script dans /usr/sbin/):

#!/usr/bin/Perl
use strict;
use warnings;

my $continue = 1;
$SIG{'TERM'}  = sub { $continue = 0; print "Caught TERM signal\n"; };
$SIG{'INT'} = sub { $continue = 0; print "Caught INT signal\n"; };

my $i = 0;
while ($continue) {
     #do stuff
     print "Hello, I am running " . ++$i . "\n";
     sleep 3;
}

Donc, ce script imprime fondamentalement quelque chose toutes les 3 secondes.

Ensuite, comme je veux démoniser ce script, j'ai également placé ce script bash (également appelé synpipe_server) dans /etc/init.d/:

#!/bin/bash
# synpipe_server : This starts and stops synpipe_server
#
# chkconfig: 12345 12 88
# description: Monitors all production pipelines
# processname: synpipe_server
# pidfile: /var/run/synpipe_server.pid
# Source function library.
. /etc/rc.d/init.d/functions

pname="synpipe_server"
exe="/usr/sbin/synpipe_server"
pidfile="/var/run/${pname}.pid"
lockfile="/var/lock/subsys/${pname}"

[ -x $exe ] || exit 0

RETVAL=0

start() {
    echo -n "Starting $pname : "
    daemon ${exe}
    RETVAL=$?
    PID=$!
    echo
    [ $RETVAL -eq 0 ] && touch ${lockfile}
    echo $PID > ${pidfile}
}

stop() {
    echo -n "Shutting down $pname : "
    killproc ${exe}
    RETVAL=$?
    echo
    if [ $RETVAL -eq 0 ]; then
        rm -f ${lockfile}
        rm -f ${pidfile}
    fi
}

restart() {
    echo -n "Restarting $pname : "
    stop
    sleep 2
    start
}

case "$1" in
    start)
        start
    ;;
    stop)
        stop
    ;;
    status)
        status ${pname}
    ;;
    restart)
        restart
    ;;
    *)
        echo "Usage: $0 {start|stop|status|restart}"
    ;; esac

exit 0

Donc, (si j'ai bien compris la documentation pour le démon), le script Perl devrait être exécuté en arrière-plan et le résultat devrait être redirigé vers /dev/null si j'exécute:

service synpipe_server start

Mais voici ce que je reçois à la place:

[root@master init.d]# service synpipe_server start
Starting synpipe_server : Hello, I am running 1
Hello, I am running 2
Hello, I am running 3
Hello, I am running 4
Caught INT signal
                                                           [  OK  ]
[root@master init.d]# 

Donc, il lance le script Perl mais l'exécute sans le détacher de la session de terminal en cours, et je peux voir le résultat imprimé dans ma console ... ce qui n'est pas vraiment ce à quoi je m'attendais. De plus, le fichier PID est vide (ou avec un saut de ligne uniquement, pas de pid renvoyé par daemon ).

Est-ce que quelqu'un a une idée de ce que je fais mal?

EDIT: je devrais peut-être dire que je suis sur une machine Red Hat.

Scientific Linux SL release 5.4 (Boron)

Merci, Tony

22
tony

J'ai finalement réécrit la fonction de démarrage dans le script bash init, et je n'utilise plus daemon.

start() {
    echo -n "Starting $pname : "
    #daemon ${exe} # Not working ...
    if [ -s ${pidfile} ]; then
       RETVAL=1
       echo -n "Already running !" && warning
       echo
    else
       Nohup ${exe} >/dev/null 2>&1 &
       RETVAL=$?
       PID=$!
       [ $RETVAL -eq 0 ] && touch ${lockfile} && success || failure
       echo
       echo $PID > ${pidfile}
    fi
}

Je vérifie que le fichier pid n’existe pas déjà (le cas échéant, écrivez simplement un avertissement). Si non, j'utilise 

 Nohup ${exe} >/dev/null 2>&1 &

pour lancer le script.

Je ne sais pas si c'est sûr comme ça (?) Mais ça marche.

16
tony

La bonne façon de démoniser un processus consiste à le détacher du terminal par lui-même. C’est ce que font la plupart des suites logicielles plus importantes, par exemple Apache .

La raison pour laquelle daemon ne fait pas ce que vous attendez de son nom et explique comment détacher un processus unix en arrière-plan peut être trouvée ici dans la section 1.7 démon?

Invoquer un programme en arrière-plan n'est pas vraiment approprié pour ces programmes de longue durée; cela ne détache pas correctement le processus de la session de terminal qui l'a démarré. Également La méthode conventionnelle de démarrage des démons consiste simplement à lancer la commande manuellement ou à partir d'un script rc; le démon est censé mettre lui-même dans le fond.

Pour en savoir plus sur ce sujet: Quelle est la différence entre Nohup et un démon?

2
MarkM

Selon man daemon, la syntaxe correcte est

daemon [options] -- [command] [command args]

Le démarrage de votre script d'initialisation devrait exécuter quelque chose comme:

daemon --pidfile ${pidfile} -- ${exe}
0
yko