Cuando escribo un demonio de Python, capto todas las excepciones y las lanzo al archivo de registro. No solo lo uso para depurar, sino también en producción. Tengo un pequeño script que ejecuto todas las mañanas que busca algo molesto en los registros.
También ayuda a mantener el demonio en funcionamiento, por supuesto.
Algún código de muestra (elimino las partes no interesantes):
import logging
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO,
format='%(asctime)s %(levelname)s %(message)s',
filename=LOG_FILE,
filemode='w')
logging.info("Sincrod inicializado")
if not DEBUG:
daemonize()
while True:
try:
actua()
except:
logging.error(sys.exc_info())
if (datetime.datetime.now().hour > NOITE_EMPEZA\
and datetime.datetime.now().hour < NOITE_REMATA):
time.sleep(INTERVALO_NOITE)
else:
time.sleep(INTERVALO_DIA)
Donde actua () es el verdadero demonio (también escribe para iniciar sesión). Tenga en cuenta que también tengo una variable DEBUG en un archivo de configuración, cuando es True, no bifurco el demonio para que se ejecute en la consola.
Demonios
Los demonios son el equivalente de Unix a los servicios de Windows. Son procesos que se ejecutan en segundo plano independientemente de otros procesos. Eso significa que su padre suele ser init, y que están separados de cualquier tty. Como son independientes, no hay un lugar predefinido para colocar su salida.
Hay muchas bibliotecas y fragmentos de Python para hacer un demonio, en el ejemplo anterior utilizo mi propia función, que combina algunas ideas de las versiones de Steinar Knutsens y Jeff Kunces. Es lo más simple posible, tenga en cuenta que me bifurco dos veces .
def daemonize():
"""Forks this process creating a daemon and killing the original one"""
if (not os.fork()):
# get our own session and fixup std[in,out,err]
os.setsid()
sys.stdin.close()
sys.stdout = NullDevice()
sys.stderr = NullDevice()
if (not os.fork()):
# hang around till adopted by init
ppid = os.getppid()
while (ppid != 1):
time.sleep(0.5)
ppid = os.getppid()
else:
# time for child to die
os._exit(0)
else:
# wait for child to die and then bail
os.wait()
sys.exit()