Nohup и Python -u: он все еще не регистрирует данные в реальном времени
При запуске процесса Python, в фоновом режиме, с
nohup python myscript.py > test.log 2>&1 < /dev/null &
проблема в том, что stdout
буферизируется: данные не записываются в реальном времени в test.log
, Общее решение этой проблемы - периодически промывать sys.stdout.flush()
или даже лучше, как предполагает этот ответ, использовать python -u
:
nohup python -u myscript.py > test.log 2>&1 < /dev/null &
Но этого недостаточно. Я заметил, что он работал в течение нескольких часов, а затем перестал работать, то есть через несколько часов test.log
больше не пишется в реальном времени, даже если я использовал nohup python -u ...
,
1) Это как воспроизвести проблему (у меня стандартный Debian Jessie). Запустите этот файл:
import time
import datetime
while True:
print datetime.datetime.now()
time.sleep(60)
с nohup python -u myscript.py > test.log 2>&1 < /dev/null &
, Файл журнала будет обновлен в течение нескольких часов, а затем через 3 или 4 часа, больше ничего.
2) Как решить эту проблему, не вставляя stdout.flush()
каждые 2 строки в коде (некрасивое решение)?
2 ответа
Если python -u не работает для вас, следующим предложением будет заменить sys.stdout пользовательским классом, который не буферизует вывод.
Магнус Лицка предоставил это решение в списке рассылки
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'
Я не могу понять, почему Python -u не будет работать на вашем примере, но это должно решить эту проблему для вас.
Есть несколько способов справиться с этим.
- Создайте свою собственную небуферизованную функцию вывода и используйте ее вместо print()
импорт системы журнал регистрации (сообщения): sys.stdout.write(MSG) sys.stdout.flush() журнал ("Привет, мир!")
Используйте команду mkfifo, чтобы создать собственное устройство регистрации и записать в него вместо stdout. Используйте отдельную команду для передачи с устройства в файл.
Напишите файл журнала напрямую и очистите, когда вы делаете. То же, что номер один, но в целом избегает использования стандартного вывода. Это то, что я бы сделал.
Я бы с подозрением относился к nohup. Терминал открывает стандартные потоки ввода / вывода и передает их процессам. Если вы запускаете процесс с nohup, а затем выходите из системы и закрываете терминал, я не уверен, что происходит со стандартными потоками. Возможно, ОС выполняет сборку мусора и закрывает их, оставляя ваш процесс без stdout. Вы действительно должны подумать о написании собственных журналов.