Nohup y Python -u: todavía no registra datos en tiempo real

Al iniciar un proceso Python, en segundo plano, con

nohup python myscript.py > test.log 2>&1 < /dev/null & 

el problema es que stdout está en búfer: los datos no se escriben en tiempo real en test.log . La solución común a este problema es vaciar periódicamente con sys.stdout.flush() , o incluso mejor, como lo sugiere esta respuesta , para usar python -u :

 nohup python -u myscript.py > test.log 2>&1 < /dev/null & 

Pero esto no es suficiente . Noté que funcionó durante unas pocas horas, y luego, dejó de funcionar, es decir , después de unas pocas horas, test.log ya no está escrito en tiempo real, incluso si usé nohup python -u ...

1) Esta es la forma de reproducir el problema (tengo un Debian Jessie estándar). Comience este archivo:

 import time import datetime while True: print datetime.datetime.now() time.sleep(60) 

con nohup python -u myscript.py > test.log 2>&1 < /dev/null & . El archivo de registro se actualizará durante unas pocas horas, y luego, después de 3 o 4 horas, nada más.

2) ¿Cómo resolver este problema , sin tener que insertar stdout.flush() cada 2 líneas en el código (solución fea)?

Si python -u no parece funcionar para usted, la siguiente sugerencia sería reemplazar sys.stdout con una clase personalizada que no genere resultados.

Magnus Lycka proporcionó esta solución en una lista de correo.

 class Unbuffered(object): def __init__(self, stream): self.stream = stream def write(self, data): self.stream.write(data) self.stream.flush() def __getattr__(self, attr): return getattr(self.stream, attr) import sys sys.stdout = Unbuffered(sys.stdout) print 'Unbuffered Output' 

No puedo ver por qué python -u no funcionaría desde tu ejemplo, pero esto debería resolver el problema por ti.

Hay múltiples formas de manejar esto.

  1. Cree su propia función de salida sin búfer y úsela en lugar de imprimir ()
 sistemas de importación

 registro de def (msg):
     sys.stdout.write (msg)
     sys.stdout.flush ()

 log ("¡Hola mundo!")
  1. Use el comando mkfifo para crear su propio dispositivo de registro y escriba en él en lugar de stdout. Use un comando separado para canalizar desde el dispositivo a un archivo.

  2. Escribe un archivo de registro directamente y descarga cuando lo hagas. Igual que el número uno, pero evita usar stdout por completo. Esto es lo que yo haría.

Yo sería sospechoso de nohup. El terminal abre flujos de entrada / salida estándar y los pasa a los procesos. Si ejecuta un proceso con nohup y luego cierra la sesión y cierra el terminal, no estoy seguro de qué sucede con los flujos estándar. Puede ser que el sistema operativo haga algún tipo de recolección de basura y los cierre, dejando su proceso sin stdout. Realmente deberías considerar escribir tus propios registros.