2011-01-16 3 views
67

Hallo,script Python comme service linux/démon

Je suis en train de laisser un script python fonctionner comme 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 élevé est difficile à obtenir le droit, mais les étapes nécessaires sont 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 en tant que gestionnaire de contexte pour entrer dans 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 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 __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 des signaux supplémentaires? Est-ce que ce sera un "processus de démon Unix bien comporté"?

Répondre

84

En supposant que votre démon ait un moyen de fonctionner en continu (certaines boucles d'événements, torsadées, etc.), vous pouvez essayer d'utiliser upstart.

Voici un exemple config arriviste pour un service Python hypothétique:

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 enregistrez ce que script.conf à /etc/init vous simplement faire une seule fois

$ sudo initctl reload-configuration 
$ sudo start script 

Vous pouvez arrêter avec stop script. Ce que dit le conf-upstart ci-dessus est de démarrer ce service au redémarrage et de le redémarrer s'il meurt. Comme pour la gestion des signaux - votre processus doit naturellement répondre à SIGTERM. Par défaut, ceci devrait être géré à moins que vous n'ayez spécifiquement installé votre propre gestionnaire de signal.

+2

Vous droit, arriviste est la norme de nos jours! Comme le script ci-dessus gère SIGTERM, il devrait être compatible avec votre fichier de configuration :) – tauran

+0

J'ai changé mon script pour qu'il soit parvenu et ça marche comme il se doit ... – tauran

+10

Un tweak supplémentaire que j'ai fait tout à l'heure. Si votre script python s'exécute sous virtualenv, il vous suffit de changer de startstart pour utiliser l'exécutable python depuis l'environnement: 'exec /home/user/.env/environ/bin/python/uns/rep/script.py' –

8

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 j'ai besoin de faire une nouvelle réponse pour pouvoir le mettre en forme correctement.

quelques autres points qui m'a pris une éternité pour debug:

  1. Quand il échoue, vérifiez d'abord /var/log/upstart/.log
  2. Si votre script implémente un démon avec , vous faites N'utilisez PAS la strophe "expect daemon". N'ayant pas d'attente, ça marche. Je ne sais pas pourquoi. (Si quelqu'un sait pourquoi - s'il vous plaît poster!)
  3. Aussi, continuez à vérifier "script d'état initctl" pour vous assurer que vous êtes en place (démarrer/courir).(Et faire un reload lorsque vous mettez à jour votre fichier de configuration)

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 
+0

Quand je copie cette config dans/etc/init puis tapez service myservicename il ne le trouve pas. Quoi de neuf avec ça. – David

+0

Avez-vous fait 'initctl reload-configuration' suivi de' service myservice start'? –

+0

Désolé, ça marche maintenant. Je tapais service service nom pensant qu'il wouod me donnerait mes options apparemment pas .... vous devez faire servicename start stop ou redémarrer. Merci pour la réponse de toute façon – David