Я написал сценарий на CentOS, а теперь пытаюсь запустить его на Ubuntu, и он ведет себя неожиданно. Вот что-то вроде сценария, который я запускаю под bash:
sudo tail -F /var/opt/my-application/log/my-application.log |
awk '
BEGIN {
ORS=" "
}
{ if ($8 ~ /MATCH-TEXT/) {
# do a whole bunch of stuff here
# like look in /proc and calculate CPU and interface stats
};
};
} '
Раньше, когда в поле $ 8 моего журнала появлялась строка с MATCH-TEXT, все "делать целую кучу вещей" (суть сценария) происходило, и я видел результат. Мое приложение генерирует строки MATCH-TEXT примерно раз в секунду (иногда больше, иногда меньше), как и результат этого скрипта.
Однако теперь, когда я запускаю этот скрипт, я долгое время не получаю вывода, а затем получаю около 30 строк вывода одновременно. Похоже, что сценарий ставит в очередь строки журнала, которые он получает, а затем выполняет несколько раз быстро, потому что вычисления на ЦП и интерфейсе подходят для «с крошечной доли секунды назад», а не «с секунды назад».
Еще более странно то, что комментирование всего содержания команды awk для замены ее на «print $ 0» (превращение всего сценария в неудобную команду grep) дает тот же результат. Так что я уверен, что это способ, которым система выполняет этот сценарий, а не что-то в самом сценарии.
Между тем, в другом окне простой "sudo tail -F my-application.log | grep MATCH-TEXT" выводится примерно каждую секунду (как и ожидалось).
Есть идеи, что здесь происходит? Есть какие-нибудь подсказки, где мне следует начать поиск причин такого поведения в очереди?
Если это не из-за разницы в tail
, то я согласен с Хауке Лагингом, что это, вероятно, проблема с буферизацией. Чтобы очистить выходной буфер awk
, попробуйте добавить fflush()
после ваших операторов печати, как я сделал в следующем тестовом коде:
tail -F /var/log/apache2/access_log | awk '{ if ($8 ~ /MATCH-TEXT/) { print $0; fflush(); }}'
Изучив все ответы и попробовав fflush и stdbuf (о которых я раньше не знал, спасибо), я обнаружил, что ответ состоит из двух частей:
1) CentOS использует gawk, Ubuntu использует mawk (по умолчанию).
У меня нет комментариев, что лучше или почему было принято решение использовать любой из них, различия - это то, что отличает два дистрибутива. (:
2) mawk имеет параметр командной строки для "интерактивного", со страницы руководства:
-W interactive
sets unbuffered writes to stdout and line buffered reads from stdin.
Records from stdin are lines regardless of the value of RS.
Я могу только предположить, что это связано с тем, что буферизация была в awk, а не в самом скрипте, что заставляет эту работу работать там, где stdbuf не работает.
mawk -W interactive устранила мою проблему в Debian Wheezy.
tail -f data.log | grep --line-buffered '$DataString' | mawk -W interactive -F "," '{print "var2", $2, "var4", $4}'