web-dev-qa-db-fra.com

Python en tant que service / démon linux

Bonjour,

J'essaie de laisser un script python s'exécuter en tant que service (démon) sur (ubuntu) linux.

Sur le web il existe plusieurs solutions comme:

http://pypi.python.org/pypi/python-daemon/

Un processus démon Unix bien comporté est difficile à réaliser, mais les étapes requises sont sensiblement les mêmes pour chaque programme démon. Une instance DaemonContext contient le comportement et l'environnement de processus configuré pour le programme; utilisez l'instance comme gestionnaire de contexte pour entrer dans un état de démon.

http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/

Cependant, comme je veux intégrer mon script python spécifiquement avec ubuntu linux, ma solution est une combinaison avec un script init.d

#!/bin/bash

WORK_DIR="/var/lib/foo"
DAEMON="/usr/bin/python"
ARGS="/opt/foo/linux_service.py"
PIDFILE="/var/run/foo.pid"
USER="foo"

case "$1" in
  start)
    echo "Starting server"
    mkdir -p "$WORK_DIR"
    /sbin/start-stop-daemon --start --pidfile $PIDFILE \
        --user $USER --group $USER \
        -b --make-pidfile \
        --chuid $USER \
        --exec $DAEMON $ARGS
    ;;
  stop)
    echo "Stopping server"
    /sbin/start-stop-daemon --stop --pidfile $PIDFILE --verbose
    ;;
  *)
    echo "Usage: /etc/init.d/$USER {start|stop}"
    exit 1
    ;;
esac

exit 0

et en python:

import signal
import time
import multiprocessing

stop_event = multiprocessing.Event()

def stop(signum, frame):
    stop_event.set()

signal.signal(signal.SIGTERM, stop)

if __== '__main__':
    while not stop_event.is_set():
        time.sleep(3)

Ma question est maintenant de savoir si cette approche est correcte. Dois-je gérer des signaux supplémentaires? Sera-ce un "processus démon Unix bien comporté"?

67
tauran

En supposant que votre démon a un moyen de s'exécuter continuellement (une boucle d'événement, une torsion, peu importe), vous pouvez essayer d'utiliser upstart.

Voici un exemple de configuration parvenu pour un service hypothétique Python:

description "My service"
author  "Some Dude <[email protected]>"

start on runlevel [234]
stop on runlevel [0156]

chdir /some/dir
exec /some/dir/script.py
respawn

Si vous l'enregistrez en tant que script.conf dans /etc/init vous faites simplement une fois

$ Sudo initctl reload-configuration
$ Sudo start script

Vous pouvez l'arrêter avec stop script. Qu'est-ce que la conf upstart ci-dessus dit est de démarrer ce service lors des redémarrages et également le redémarrer s'il meurt.

Quant à la gestion du signal - votre processus devrait naturellement répondre à SIGTERM. Par défaut, cela doit être géré sauf si vous avez spécifiquement installé votre propre gestionnaire de signaux.

87
rlotun

La réponse de Rloton est bonne. Voici un léger raffinement, juste parce que j'ai passé une tonne de débogage. Et je dois faire une nouvelle réponse pour pouvoir formater correctement.

Quelques autres points qui m'ont pris une éternité pour déboguer:

  1. En cas d'échec, vérifiez d'abord /var/log/upstart/.log
  2. Si votre script implémente un démon avec python-daemon , vous n'utilisez PAS la strophe 'expect daemon'. Ne pas avoir de travaux "attendus". Je ne sais pas pourquoi. (Si quelqu'un sait pourquoi - veuillez poster!)
  3. En outre, continuez à vérifier "script d'état initctl" pour vous assurer que vous êtes en place (démarrage/exécution). (et effectuez un rechargement lorsque vous mettez à jour votre fichier conf)

Voici ma version:

description "My service"
author  "Some Dude <[email protected]>"

env PYTHON_HOME=/<pathtovirtualenv>
env PATH=$PYTHON_HOME:$PATH

start on runlevel [2345]
stop on runlevel [016]

chdir <directory>

# NO expect stanza if your script uses python-daemon
exec $PYTHON_HOME/bin/python script.py

# Only turn on respawn after you've debugged getting it to start and stop properly
respawn
9
Ross R