У меня есть выполнение сценария, которое передает его вывод по каналу через другой сценарий; тот сценарий обертки добавляет метку времени к каждой строке журнала. Однако данные пишутся в файл журнала в блоках приблизительно 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
Первопричиной является Ваш процесс, здесь 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 пишет свой вывод).
Поскольку поток 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()