J'ai besoin d'installer un programme en tant que service dans Red Hat. Il ne se déroule pas en arrière-plan, ne gère pas son fichier PID ou ne gère pas ses propres journaux. Il s'exécute et s'imprime simplement sur STDOUT et STDERR.
En utilisant les scripts init standard comme guides, j'ai développé ce qui suit:
#!/bin/bash
#
# /etc/rc.d/init.d/someprog
#
# Starts the someprog daemon
#
# chkconfig: 345 80 20
# description: the someprog daemon
# processname: someprog
# config: /etc/someprog.conf
# Source function library.
. /etc/rc.d/init.d/functions
prog="someprog"
exec="/usr/local/bin/$prog"
[ -e "/etc/sysconfig/$prog" ] && . "/etc/sysconfig/$prog"
lockfile="/var/lock/subsys/$prog"
RETVAL=0
check() {
[ `id -u` = 0 ] || exit 4
test -x "$exec" || exit 5
}
start() {
check
if [ ! -f "$lockfile" ]; then
echo -n $"Starting $prog: "
daemon --user someproguser "$exec"
RETVAL=$?
[ $RETVAL -eq 0 ] && touch "$lockfile"
echo
fi
return $RETVAL
}
stop() {
check
echo -n $"Stopping $prog: "
killproc "exec"
RETVAL=$?
[ $RETVAL -eq 0 ] && rm -f "$lockfile"
echo
return $RETVAL
}
restart() {
stop
start
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
status)
status "$prog"
RETVAL=$?
;;
*)
echo $"Usage: $0 {start|stop|restart|status}"
RETVAL=2
esac
exit $RETVAL
Il se peut que mon erreur ait été de copier-coller et de modifier certains des scripts existants dans /etc/init.d. Dans tous les cas, le service résultant se comporte étrangement:
- quand je le démarre avec
service someprog start
le programme imprime sur le terminal et la commande ne se termine pas. - si je CTRL-C, il affiche "Session terminée, tuant shell ... ... tué. ÉCHEC". Je dois le faire pour récupérer à nouveau mon invite shell.
- maintenant, quand je lance,
service someprog status
il dit qu'il fonctionne et répertorie son PID. Je peux le voirps
donc il fonctionne. - maintenant, quand je cours,
service someprog stop
il n'arrête pas. Je peux vérifier qu'il fonctionne toujours avecps
.
Que dois-je changer pour qu'il someprog
soit envoyé en arrière-plan et géré en tant que service?
Edit: J'ai maintenant trouvé quelques questions connexes, aucune d'entre elles avec une réponse réelle autre que "faire autre chose":
- L'appel au démon dans un script /etc/init.d bloque, ne s'exécute pas en arrière-plan
- Obtenir un script shell à exécuter en tant que démon sur CentOS?
Edit: cette réponse sur le double forking a peut-être résolu mon problème, mais maintenant mon programme lui-même double-forks et cela fonctionne: /programming//a/9646251/898699
Réponses:
La commande "ne se termine pas" car la
daemon
fonction n'exécute pas votre application en arrière-plan pour vous. Vous devrez ajouter un&
à la fin de votredaemon
commande comme ceci:daemon --user someproguser $exec &
Si
someprog
ne gère pasSIGHUP
, vous devez exécuter la commande avecnohup
pour vous assurer que votre processus ne recevra pas,SIGHUP
ce qui indique à votre processus de se terminer à la fermeture du shell parent. Cela ressemblerait à ceci:daemon --user someproguser "nohup $exec" &
Dans votre
stop
fonction,killproc "exec"
ne fait rien pour arrêter votre programme. Il devrait se lire comme suit:killproc $exec
killproc
nécessite le chemin d'accès complet à votre application pour l'arrêter correctement. J'ai eu quelques problèmes aveckillproc
le passé, vous pouvez donc aussi simplement tuer le PID dans le PIDFILE auquel vous devriez écriresomeprog
le PID avec quelque chose comme ceci:cat $pidfile | xargs kill
Vous pouvez écrire le PIDFILE comme ceci:
ps aux | grep $exec | grep -v grep | tr -s " " | cut -d " " -f2 > $pidfile
où
$pidfile
pointe/var/run/someprog.pid
.Si vous voulez [OK] ou [ÉCHEC] sur votre
stop
fonction, vous devez utiliser les fonctionssuccess
et àfailure
partir de/etc/rc.d/init.d/functions
. Vous n'en avez pas besoin dans lastart
fonction, car elledaemon
appelle celle qui vous convient.Vous n'avez également besoin que de guillemets autour des chaînes avec des espaces. C'est un choix de style, donc c'est à vous de décider.
Tous ces changements ressemblent à ceci:
la source
S'il s'agit de votre programme, veuillez l'écrire en tant que démon approprié. Surtout si c'est pour la redistribution. :)
Vous pourriez essayer monit . Ou peut-être quelque chose comme runit ou daemontools. Ces puissants n'ont pas de packages facilement disponibles. Daemontools est de DJB, si cela influence votre décision (dans les deux sens.)
la source
J'ai fait quelques recherches supplémentaires et il semble que la réponse soit «vous ne pouvez pas faire ça». Le programme à exécuter doit en fait se démonifier correctement: bifurquer et détacher ses descripteurs de fichiers standard, se détacher du terminal et démarrer une nouvelle session.
Edit: apparemment je me trompe - une double fourche fonctionnerait. /programming//a/9646251/898699
la source