Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nohup and Python -u : it still doesn't log data in realtime

When launching a Python process, in background, with

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

the problem is that stdout is buffered: the data is not written in realtime to test.log. The common solution to this problem is to flush periodically with sys.stdout.flush(), or even better, as suggested by this answer, to use python -u :

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

But this is not enough. I noticed that it worked during a few hours, and then, it stopped working, i.e. after a few hours test.log is not written in realtime anymore, even if I used nohup python -u ....

1) This is how to reproduce the problem (I have a standard Debian Jessie). Start this file:

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

with nohup python -u myscript.py > test.log 2>&1 < /dev/null &. The log file will be updated during a few hours, and then after 3 or 4 hours, nothing anymore.

2) How to solve this problem, without having to insert stdout.flush() every 2 lines in the code (ugly solution) ?

like image 591
Basj Avatar asked Jan 12 '16 21:01

Basj


People also ask

How do you know when nohup is done?

To check the results or status of the programs, log back in to the same server. Once the job has finished its output will be contained in a file located within your home space. The filename will be "nohup. out" (no quotes).

Where do nohup logs go?

Since there isn't a terminal to associate with it, nohup logs everything to an output file, nohup. out . By default, that file is located in whichever directory you started the command in. nohup.

Why nohup out is empty?

The short answer is to use nohup python -u args... to force python to print and flush buffer for each print() call. I believe this is due to Python's default behaviour to write to buffer first, but nohup doesn't trigger the buffer to be cleared.

Does nohup run in background?

The nohup command can also be used to run programs in the background after logging off. To run a nohup command in the background, add an & (ampersand) to the end of the command.


1 Answers

If python -u does not seem to be working for you, the next suggestion would be to replace sys.stdout with a custom class that does not buffer output.

Magnus Lycka provided this solution in a mailing list

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'

I can't see why python -u wouldn't work from your example, but this should solve the issue for you.

like image 148
Cody Avatar answered Sep 18 '22 07:09

Cody