Ejecute un programa desde Python y haga que continúe ejecutándose después de que se elimine el script.
Intenté ejecutar cosas como esta:
subprocess.Popen(['nohup', 'my_command'],
stdout=open('/dev/null', 'w'),
stderr=open('logfile.log', 'a'))
Esto funciona si el script principal sale correctamente, pero si elimino el script (Ctrl-C), todos mis procesos secundarios también se eliminan. Hay alguna manera de evitar esto?
Las plataformas que me interesan son OS X y Linux, que usan Python 2.6 y Python 2.7.
El proceso hijo recibe lo mismo SIGINT
que su proceso padre porque está en el mismo grupo de procesos. Puede colocar al hijo en su propio grupo de procesos llamando os.setpgrp()
al proceso hijo. Popen
El argumento de preexec_fn
es útil aquí:
subprocess.Popen(['nohup', 'my_command'],
stdout=open('/dev/null', 'w'),
stderr=open('logfile.log', 'a'),
preexec_fn=os.setpgrp
)
( preexec_fn
Es solo para un*x-oids. Parece haber un equivalente aproximado para Windows " creationflags=CREATE_NEW_PROCESS_GROUP
", pero nunca lo he probado).
La forma habitual de hacer esto en sistemas Unix es bifurcar y salir si eres el padre. Mira esto os.fork()
.
Aquí hay una función que hace el trabajo:
def spawnDaemon(func):
# do the UNIX double-fork magic, see Stevens' "Advanced
# Programming in the UNIX Environment" for details (ISBN 0201563177)
try:
pid = os.fork()
if pid > 0:
# parent process, return and keep running
return
except OSError, e:
print >>sys.stderr, "fork #1 failed: %d (%s)" % (e.errno, e.strerror)
sys.exit(1)
os.setsid()
# do second fork
try:
pid = os.fork()
if pid > 0:
# exit from second parent
sys.exit(0)
except OSError, e:
print >>sys.stderr, "fork #2 failed: %d (%s)" % (e.errno, e.strerror)
sys.exit(1)
# do stuff
func()
# all done
os._exit(os.EX_OK)
Desde 3.2 también puedes usar start_new_session
flag (solo POSIX).
import subprocess
p = subprocess.Popen(["sleep", "60"], start_new_session=True)
ret = p.wait()
Ver start_new_session en el constructor Popen