Script Python en tant que service linux/démon

Bonjour,

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

Sur le web, il existe plusieurs solutions comme:

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

Un processus de démon Unix bien comporté est difficile à obtenir, mais les étapes requises sont à peu près les mêmes pour chaque programme de 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 un État 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 init.d script

#!/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 __name__ == '__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 tout de signaux supplémentaires? Sera-ce un "processus démon Unix bien comporté"?

67
demandé sur tauran 2011-01-16 16:20:57

2 réponses

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

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

description "My service"
author  "Some Dude <blah@foo.com>"

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

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

Si vous enregistrez ce script.conf à /etc/init vous faites simplement un

$ sudo initctl reload-configuration
$ sudo start script

, Vous pouvez l'arrêter avec stop script. Ce que dit la conf upstart ci-dessus est de démarrer ce service au redémarrage et de le redémarrer s'il meurt.

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

86
répondu rlotun 2011-01-16 16:03:29

La réponse de Rloton est bonne. Voici un léger raffinement, juste parce que j'ai passé une tonne de temps à déboguer. 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. quand il échoue, 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 "s'attendre" fonctionne. Je ne sais pas pourquoi. (Si quelqu'un sait pourquoi-s'il vous plait post!)
  3. aussi, continuez à vérifier "initctl status script" pour vous assurer que vous êtes en place (Démarrer / Exécuter). (et faites un rechargement lorsque vous mettez à jour votre fichier conf)

Voici ma version:

description "My service"
author  "Some Dude <blah@foo.com>"

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
répondu Ross R 2014-02-14 00:34:56