2009-06-09 12 views
11

im desove un script que se ejecuta durante mucho tiempo de una aplicación web como esta:proceso de desove de pitón

os.spawnle(os.P_NOWAIT, "../bin/producenotify.py", "producenotify.py", "xx",os.environ) 

la secuencia de comandos se genera con éxito y que corre, sino hasta que se sobrepone que no soy capaz de liberar el puerto que usa la aplicación web, o en otras palabras, no puedo reiniciar la aplicación web. ¿Cómo genero un proceso y lo hago completamente independiente de la aplicación web?

esto está en linux os.

+1

¿Por qué no utiliza el subproceso.Pobre para hacer esto? –

+2

S. Lott: ¿podré matar/reiniciar la aplicación web/proceso principal después de hacer el subproceso.Popen? gracias – mark

Respuesta

26

Como @ Marcos aclaró que es un sistema Linux, el guión podría fácilmente hacerse totalmente independiente, es decir, un demonio , siguiendo este recipe. (También puede hacerlo en el padre después de os.fork y solo entonces os.exec... el proceso secundario).

Editar: para aclarar algunos detalles Comentario de wrt @ mark sobre mi respuesta: los privilegios de superusuario no son necesarios para "daemonizar" un proceso según las recetas del libro de cocina, ni hay necesidad de cambiar el directorio de trabajo actual (aunque el código en la receta hace eso y más, esa no es la parte crucial, sino que es la secuencia lógica adecuada de las llamadas fork, _exit y setsid). Las diversas variantes os.exec... que hacen no terminan en e utilizan el entorno del proceso principal, por lo que esa parte también es fácil - consulte Python online docs.

Para abordar sugerencias hechas en los comentarios y respuestas de otros: creo que subprocess y multiprocessing per se no daemonize el proceso secundario, que parece ser lo que @mark necesita; la secuencia de comandos podría hacerlo por sí mismo, pero desde un código tiene que estar haciendo fork sy setsid, me parece mejor mantener todo el desove en ese plano de bajo nivel en lugar de mezclar algunos de alto nivel y algunos bajos código de nivel en el curso de la operación.

Aquí hay una versión muy reducida y simplificada de la receta en la URL anterior, diseñada para ser llamada en el padre para generar un hijo daemon - de esta manera, el código se puede usar para ejecutar ejecutables que no sean de Python. . Como se indica, el código debe cumplir con las necesidades @mark explicadas, por supuesto, se puede adaptar de muchas maneras: recomiendo leer la receta original y sus comentarios y discusiones, así como los libros que recomienda, para obtener más información.

import os 
import sys 

def spawnDaemon(path_to_executable, *args) 
    """Spawn a completely detached subprocess (i.e., a daemon). 

    E.g. for mark: 
    spawnDaemon("../bin/producenotify.py", "producenotify.py", "xx") 
    """ 
    # fork the first time (to make a non-session-leader child process) 
    try: 
     pid = os.fork() 
    except OSError, e: 
     raise RuntimeError("1st fork failed: %s [%d]" % (e.strerror, e.errno)) 
    if pid != 0: 
     # parent (calling) process is all done 
     return 

    # detach from controlling terminal (to make child a session-leader) 
    os.setsid() 
    try: 
     pid = os.fork() 
    except OSError, e: 
     raise RuntimeError("2nd fork failed: %s [%d]" % (e.strerror, e.errno)) 
     raise Exception, "%s [%d]" % (e.strerror, e.errno) 
    if pid != 0: 
     # child process is all done 
     os._exit(0) 

    # grandchild process now non-session-leader, detached from parent 
    # grandchild process must now close all open files 
    try: 
     maxfd = os.sysconf("SC_OPEN_MAX") 
    except (AttributeError, ValueError): 
     maxfd = 1024 

    for fd in range(maxfd): 
     try: 
      os.close(fd) 
     except OSError: # ERROR, fd wasn't open to begin with (ignored) 
      pass 

    # redirect stdin, stdout and stderr to /dev/null 
    os.open(os.devnull, os.O_RDWR) # standard input (0) 
    os.dup2(0, 1) 
    os.dup2(0, 2) 

    # and finally let's execute the executable for the daemon! 
    try: 
     os.execv(path_to_executable, args) 
    except Exception, e: 
     # oops, we're cut off from the world, let's just give up 
     os._exit(255) 
+0

alex, es un sistema unix. fedora linux. la aplicación web no tiene privilegios de superusuario. ¿es eso un problema? también el daemon debe tener el mismo directorio de trabajo y variables de entorno que la aplicación web. ¿Cómo logro esto? gracias – mark

+0

déjame editar mi respuesta para agregar estos bits de información. –

+0

alex, tx para aclaración. Revisé la receta y es un poco confuso. es ese código en la aplicación web principal? o entra en el nuevo script que se va a generar? ¡muchas gracias de nuevo! – mark

12

Puede usar la biblioteca de multiprocesamiento para generar procesos. Aquí se muestra un ejemplo básico:

from multiprocessing import Process 

def f(name): 
    print 'hello', name 

if __name__ == '__main__': 
    p = Process(target=f, args=('bob',)) 
    p.start() 
    p.join() 
+0

+1 multiprocesamiento pythonic! – SingleNegationElimination

+6

esto tiene el problema de que el proceso principal no se puede eliminar hasta que se complete el subproceso. ¡Gracias! – mark

+0

* Nota * La biblioteca 'multiprocesamiento' se agregó a Python 2.6. Aquí hay documentación http://docs.python.org/library/multiprocessing.html – Ciantic