Файлы журнала записаны в то, когда буфер заполняется или в 'в реальном времени'?

У меня есть выполнение сценария, которое передает его вывод по каналу через другой сценарий; тот сценарий обертки добавляет метку времени к каждой строке журнала. Однако данные пишутся в файл журнала в блоках приблизительно 8 000 символов (примерно 180 строк). Это заставляет все те строки быть добавленными метку времени точно то же. Если базовый скрипт, который производит информацию, запущен непосредственно в оболочке затем, выводы появляются линию за линией в режиме реального времени.

Для ссылки сценарий похож на это:

#!/bin/bash
python foo.py | ~/timestamp.sh >> ~/logs/foo.log
exit

Сценарий метки времени просто добавляет a, Вы предположили это, метка времени к каждой строке вывода. Тот сценарий содержит следующее:

#!/bin/bash
while read x; do
  echo -n `date +%d/%m/%Y\ %H:%M:%S`;
  echo -n " ";
  echo $x;
done

Если я удаляю timestamp.sh из уравнения, поведение является точно тем же. Я проверил это путем запущения скрипта и контроля использования файла журнала tail -f script.log

Существует ли установка, которая буферизует вывод файла прежде, чем записать это в файлы журнала? Есть ли другие методы, я могу попытаться добавить метку времени к каждой строке файла журнала? У меня был этот тип вещи работа прежде над предыдущими системами, но независимо от того, что я ничего не пробую, кажется, сортирует это.

Это - все на Ubuntu 14.04.4 x64

0
задан 22 June 2016 в 18:03

2 ответа

Первопричиной является Ваш процесс, здесь python, использует libc stdout, где вывод является строкой, буферизованной, когда произведено к терминалу, но блоку, буферизованному, когда произведено к чему-то еще, как канал здесь.

можно устранить проблему любой в коде Python путем явного сбрасывания буфера после того, как каждый журнал произведет:

sys.stdout.flush()

или путем управления, как буферизация будет сделана с некоторым взломом:

stdbuf -oL python foo.py | ~/timestamp.sh >> ~/logs/foo.log

или

unbuffer python foo.py | ~/timestamp.sh >> ~/logs/foo.log

я рекомендовал бы явно сбросить буфер в Вашем коде (sys.stdout.flush()), поскольку Вы - единственный для знания точно, где вывод должен быть сброшен. Строка, буферизующая (stdbuf -oL), немного менее оптимизирована, но должна быть в порядке, учитывая факт, к которому Вы добавляете метку времени на строку, и запрещающий всю буферизацию (unbuffer, или heemayl's python -u предложение) худший подход, что касается производительности (хотя могло бы быть непримечательно в зависимости от того, как Ваш код Python пишет свой вывод).

1
ответ дан 29 September 2019 в 01:41

Поскольку поток STDOUT является блоком, буферизованным по умолчанию (если не идущий в терминал) python, необходимо сделать поток освободившим буфер (или строка буферизованный).

python позволяет делать потоки освободившими буфер, вот является Pythonic путем:

python -u foo.py

Так, Ваша целая командная строка становится:

python -u foo.py | ~/timestamp.sh >> ~/logs/foo.log

От man python:

-u     Force stdin, stdout and stderr to be totally unbuffered
<час>

я теперь знаю о Вашем сценарии, но в рамках сценария можно сбросить определенный поток с помощью sys модуль:

sys.stdout.flush()
1
ответ дан 29 September 2019 в 01:41

Другие вопросы по тегам:

Похожие вопросы: