2011-01-16 31 views
67

Hola,script de Python como un servicio Linux/daemon

estoy tratando de dejar que un script en Python funcionar como servicio (demonio) en Linux (Ubuntu).

En la web existen varias soluciones como:

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

Un proceso demonio Unix buen comportamiento es difícil de hacerlo bien, pero los pasos requeridos son prácticamente los mismos para cada programa demonio. Una instancia de DaemonContext contiene el comportamiento y el entorno de proceso configurado para el programa; use la instancia como administrador de contexto para ingresar un estado de daemon.

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

Sin embargo ya que quiero integrar mi script en Python, específicamente con Ubuntu Linux mi solución es una combinación con un script de 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 

y 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) 

Mi pregunta ahora es si este enfoque es correcto. ¿Debo manejar alguna señal adicional? ¿Será un "proceso de demonio de Unix de buen comportamiento"?

Respuesta

84

Suponiendo que su daemon tiene alguna forma de ejecución continua (algún bucle de evento, retorcido, lo que sea), puede intentar usar upstart.

He aquí un ejemplo de configuración para un servicio advenedizo Python hipotética:

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 guarda esto como script.conf a /etc/init que hacen sencilla de una sola vez

$ sudo initctl reload-configuration 
$ sudo start script 

Puede detenerlo con stop script. Lo que dice la nueva versión del upstart conf es iniciar este servicio al reiniciar y también reiniciarlo si se muere.

En cuanto a la gestión de señal, su proceso debe responder naturalmente a SIGTERM. De forma predeterminada, esto debe manejarse a menos que haya instalado específicamente su propio manejador de señal.

+2

Se derecha, recién llegado es el estándar hoy en día! Como la secuencia de comandos anterior maneja SIGTERM, debería estar bien con su archivo de configuración :) – tauran

+0

Cambié la secuencia de comandos a advenedizo y funciona como debería ... – tauran

+10

Un ajuste adicional que hice justo ahora. Si su script de python se ejecuta bajo un virtualenv, solo necesita cambiar el upstart para usar el ejecutable de python del entorno: 'exec /home/user/.env/environ/bin/python/some/dir/script.py' –

8

La respuesta de Rloton es buena. Aquí hay un refinamiento ligero, solo porque pasé un montón de tiempo depurando. Y necesito hacer una nueva respuesta para poder formatear correctamente.

Un par de otros puntos que me llevó para siempre a depurar:

  1. Cuando falla, compruebe primero /var/log/upstart/.log
  2. Si su script implementa un demonio con , que hacen NO use la estrofa 'expect daemon'. No tener 'esperar' funciona. No sé por qué. (Si alguien sabe por qué, por favor, publíquelo)
  3. Además, siga revisando "initctl status script" para asegurarse de que está activo (inicio/ejecución).(Y hacer una recarga al actualizar el archivo de configuración)

Aquí está mi versión:

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

Cuando copio esta configuración en/etc/init luego escriba service myservicename no lo encuentra. Que pasa con eso. – David

+0

¿Hizo 'initctl reload-configuration' seguido de' service myservice start'? –

+0

Lo siento, funciona ahora. Estaba escribiendo el nombre del servicio del servicio pensando que probablemente me daría mis opciones, al parecer no ... tiene que hacer el inicio del servicio detener o reiniciar. Gracias por la respuesta de todos modos – David

Cuestiones relacionadas