анализ лога с помощью sed или grep - PullRequest
4 голосов
/ 12 ноября 2011

Я хочу получить данные из этого вида журнала.

12 ноября 13:46:14 Home cxxd [8892]: 208 11/12 13: 46: 14 |qc = IN (1), qt = A (1), query = "www.yahoo.com."

Реализовано это, которое дает мне URL.Но не работает с "TAIL -F", так что я мог отслеживать в реальном времени только URL.

tail -100 /var/log/system.log |grep "query =" |sed -e "s /.* query = //" |sed -e "s / \" // g "| sed -e" s /.$/ / "

Пожалуйста, предложите или улучшите

Ответы [ 3 ]

6 голосов
/ 12 ноября 2011

Я ожидаю, что несколько sed сценариев делают работают с выводом tail -F, но не так, как вы ожидаете.

Стандартные библиотеки ввода-вывода C будут выполнять буферизацию для повышения производительности. Библиотека IO не может выполнять (а) отсутствие буферизации (б) буферизацию строки (в) блочную буферизацию. Буферизация строки обычно выбирается, если выход идет на терминал. Но если вывод идет в файл или канал, тогда обычно выбирается блочная буферизация. (Это сложнее, чем это - поведение меняется, если рассматриваемый файловый дескриптор используется для stdout или stderr или другого файла. См. setvbuf(3) для получения полной информации.)

Итак, хотя буферизация блоков, которую вы видите сейчас, вероятно, лучше для производительности , это означает, что вы можете подождать некоторое время, прежде чем увидите какой-либо вывод, поскольку каждая команда в конечном итоге накапливает блок данных. По крайней мере, grep(1) позволяет опции командной строки --line-buffered использовать буферизацию строки, а sed(1) позволяет опции командной строки --unbuffered чаще очищать выходные буферы. Итак, попробуйте это:

tail -f /var/log/system.log | grep --line-buffered "query=" | sed -u -e "s/.*query=//" | sed -u -e "s/\"//g" | sed -u -e "s/.$/ /"

(Я не нашел аналогичных опций для tail(1), но даже если он отправляет блоки данных другим, изменения в grep(1) и sed(1) окажут существенную помощь.)

5 голосов
/ 12 ноября 2011

Попробуйте уменьшить число каналов, заменив несколько вызовов на grep и sed на один с awk:

tail -f /var/log/system.log | awk -F'=' '/query=/ { sub(/^"/, "", $NF); sub(/."$/, "", $NF); print $NF }'

..., в котором каждая строка соответствует запросу = изахватывает все после последнего '=', заменяет первый '' 'и завершающий'. "'и печатает результат.

0 голосов
/ 12 ноября 2011

Попробуйте аргументы tail -f и grep --line-buffered

...