2009-02-26 26 views
23

Tengo una herramienta que he escrito en python y generalmente debería ejecutarse como daemon. ¿Cuáles son las mejores prácticas para empaquetar esta herramienta para su distribución, particularmente cómo se deben manejar los archivos de configuración y el script/ejecutable daemon?Python Daemon Packaging Best Practices

En relación con esto ¿hay herramientas comunes para configurar el demonio para que se ejecutan en el arranque como apropiados para la plataforma dada (es decir init scripts en Linux, servicios en las ventanas, launchd en OS X)?

+1

Vea también esta pregunta ASÍ: http://stackoverflow.com/questions/473620/how-do-you-create-a-daemon-in-python – Rabarberski

Respuesta

11

Para responder a una parte de su pregunta, no existen herramientas que conozco que va a hacer la configuración demonio de forma portátil incluso a través de los sistemas Linux permitir que Windows solos o Mac OS X.

distribuciones

La mayoría de Linux parecen estar usando start-stop-daemon dentro init scripts ahora, pero aún tendrá una pequeña diferencia en el diseño del sistema de archivos y grandes diferencias en el empaquetado. El uso de autotools/Configurar o distutils/easy_install si su proyecto es todo Python, que recorrer un largo camino para hacer que sea más fácil para construir paquetes para diferentes distribuciones de Linux/BSD.

Windows es un juego completamente diferente y requerirá extensiones Mark Hammond's win32 y quizás Tim Golden's WMI extensiones.

No sé Launchd excepto que "ninguna de las anteriores" son relevantes.

Para obtener consejos sobre daemonizing scripts de Python, me gustaría ver a aplicaciones Python que en realidad lo están haciendo en el mundo real, por ejemplo dentro de trenzado.

14

La mejor herramienta que encontré para ayudar con las secuencias de comandos init.d es "start-stop-daemon". Ejecutará cualquier aplicación, supervisará los archivos run/pid, los creará cuando sea necesario, proporcionará formas de detener el daemon, establecerá los ID del usuario/grupo del proceso e incluso podrá crear un fondo de su proceso.

Por ejemplo, este es un script que puede iniciar/detener un servidor WSGI:

#! /bin/bash 

case "$1" in 
    start) 
    echo "Starting server" 

    # Activate the virtual environment 
    . /home/ali/wer-gcms/g-env/bin/activate 

    # Run start-stop-daemon, the $DAEMON variable contains the path to the 
    # application to run 
    start-stop-daemon --start --pidfile $WSGI_PIDFILE \ 
     --user www-data --group www-data \ 
     --chuid www-data \ 
     --exec "$DAEMON" 
    ;; 
    stop) 
    echo "Stopping WSGI Application" 

    # Start-stop daemon can also stop the application by sending sig 15 
    # (configurable) to the process id contained in the run/pid file 
    start-stop-daemon --stop --pidfile $WSGI_PIDFILE --verbose 
    ;; 
    *) 
    # Refuse to do other stuff 
    echo "Usage: /etc/init.d/wsgi-application.sh {start|stop}" 
    exit 1 
    ;; 
esac 

exit 0 

También puede ver que hay un ejemplo de cómo usarlo con un virtualenv, que siempre recomendaría.

-10

"generalmente debería ejecutarse como daemon?"

No - en la superficie - tiene mucho sentido. "Generalmente" no es sensato. Es un daemon o no. Es posible que desee actualizar su pregunta.

Para ver ejemplos de daemons, lea sobre daemons como el httpd de Apache o cualquier servidor de base de datos (son daemons) o el daemon de correo SMTPD.

O, tal vez, lea sobre algo más simple, como el daemon FTP, daemon SSH, daemon Telnet.

En Linux World, tendrá el directorio de instalación de su aplicación, algún directorio de trabajo, más los directorios del archivo de configuración.

Utilizamos /opt/ourapp para la aplicación (que es Python, pero no lo instale en lib/site-packages de Python)

Utilizamos /var/ourapp para archivos de trabajo y nuestros archivos de configuración.

Podríamos usar /etc/ourapp para los archivos de configuración, sería coherente, pero no es así.

Todavía no utilizamos los scripts init.d para el inicio. Pero esa es la última pieza, inicio automatizado. Por ahora, tenemos administradores de sistema que inician los daemons.

Esto se basa, en parte, en http://www.pathname.com/fhs/ y http://tldp.org/LDP/Linux-Filesystem-Hierarchy/html/Linux-Filesystem-Hierarchy.html.

+2

Eres bonita ¡duro! Los daemons son solo programas que se demonizan. A veces es útil ejecutarlos como un proceso regular para Ctrl-c, verificar la salida en stdout, etc. – fulmicoton

+0

@Paul: De acuerdo. ¿Puedes aclarar la pregunta? –

0

En los sistemas Linux, el administrador de paquetes del sistema (Portage para Gentoo, Aptitude para Ubuntu/Debian, yum para Fedora, etc.) generalmente se encarga de instalar el programa, incluso colocando los scripts init en los lugares correctos. Si desea distribuir su programa para Linux, es posible que desee buscar en agruparlo en el formato adecuado para los administradores de paquetes de varias distribuciones.

Este consejo es obviamente irrelevante en sistemas que no tienen gestores de paquetes (Windows y Mac, creo).

+0

¡Hay sistemas de embalaje para muchos otros Unices! Por ejemplo, pkgsrc para NetBSD. – bortzmeyer

+0

Interesante, no sabía que –

8

Hay muchos fragmentos de la oferta de Internet para escribir un demonio en Python puro (no scripts Bash)

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

Si desea escribir su propia,
la principio es el mismo que con la función daemon bash.

Básicamente:

En el arranque:

  • de tenedor a otro proceso
  • abrir un archivo de registro para redirigir su stdout y stderr
  • Guardar el pid en alguna parte.

En parada:

  • usted envía SIGTERM al proceso con pid almacenada en su pidfile.
  • Con signal.signal (signal.SIGTERM, sigtermhandler) que se puede unir un procedimiento parar a la señal SIGTERM.

No conozco ningún paquete ampliamente utilizado que haga esto.

+1

+1 Para el daemon de Python. De hecho, uso una receta similar a esta, excepto que la lance con start-stop-daemon desde un script Bash. Tal vez un paso más, pero me da una sensación cálida y difusa de comportarme como todos los demás demonios. –

3

No puedo recordar donde he descargado ... pero este es el mejor guión daemonizing que he encontrado. Funciona muy bien (en Mac y Linux.) (Guardarlo como daemonize.py)

import sys, os 
def daemonize (stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): 
    # Perform first fork. 
    try: 
     pid = os.fork() 
     if pid > 0: 
      sys.exit(0) # Exit first parent. 
    except OSError, e: 
     sys.stderr.write("fork #1 failed: (%d) %sn" % (e.errno, e.strerror)) 
     sys.exit(1) 
    # Decouple from parent environment. 
    os.chdir("/") 
    os.umask(0) 
    os.setsid() 
    # Perform second fork. 
    try: 
     pid = os.fork() 
     if pid > 0: 
      sys.exit(0) # Exit second parent. 
    except OSError, e: 
     sys.stderr.write("fork #2 failed: (%d) %sn" % (e.errno, e.strerror)) 
     sys.exit(1) 
    # The process is now daemonized, redirect standard file descriptors. 
    for f in sys.stdout, sys.stderr: f.flush() 
    si = file(stdin, 'r') 
    so = file(stdout, 'a+') 
    se = file(stderr, 'a+', 0) 
    os.dup2(si.fileno(), sys.stdin.fileno()) 
    os.dup2(so.fileno(), sys.stdout.fileno()) 
    os.dup2(se.fileno(), sys.stderr.fileno()) 

En su guión, sólo tendría que:

from daemonize import daemonize 
daemonize() 

Y también puede especificar lugares para redirigir la stdio , err, etc ...

+4

se parece a una acumulación temprana de ésta: http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/ –

3

No es una bala de plata para lo que estás pidiendo, pero echa un vistazo a supervisord.Maneja todos los bits divertidos de los procesos de gestión. Lo uso mucho en un entorno de producción grande. Además, está escrito en Python!

0

Este blog entry dejaron claro para mí que en realidad hay dos formas comunes de ejecutar su programa Python como un demonio (no lo había descubierto tan claramente a partir de las respuestas existentes):

Hay dos enfoques para escribir aplicaciones de daemon como servidores en Python.

  • La primera es realizar todas las tareas de sarting y demonios de frenado en sí código Python. La forma más fácil de hacer esto es con el paquete python-daemon que eventualmente podría hacer su camino en la distribución de Python.

Poeljapon's answer es un ejemplo de esta primera aproximación, aunque no utiliza el paquete python-daemon, pero los enlaces a una costumbre script en Python, pero muy limpio.

  • El otro método consiste en utilizar las herramientas suministrados por el sistema operativo. En el caso de Debain, esto significa escribiendo un script de inicio que hace uso del programa start-stop-daemon .

Ali Afshar's answer es un ejemplo de script shell del segundo enfoque, usando el start-stop-daemon.

La entrada de blog que cité tiene un ejemplo de script de shell y algunos detalles adicionales sobre cosas como iniciar el daemon al iniciar el sistema y reiniciar automáticamente su daemon cuando se detuvo por algún motivo.

0

corrígeme si está mal, pero creo que la pregunta es cómo DEPLOY el daemon. Configure su aplicación para instalarla a través de pip y luego haga que entry_point sea cli(daemon()). A continuación, cree un guión de inicio que simplemente ejecute $app_name &