Назад | Перейти на главную страницу

сценарий tail-pipe-awk, нормально на Centos, но странно на Ubuntu

Я написал сценарий на 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}'