2016-01-31 6 views
0

У меня есть большой файл журнала размером до 3 ГБ.Оптимизация поиска в linux

Моя задача - генерировать некоторую отчетность, основанную на # раз, когда что-то регистрируется.

Мне нужно найти время, когда StringA, StringB, StringC вызывается отдельно.

Что я делаю прямо сейчас:

grep "StringA" server.log | wc -l 
grep "StringB" server.log | wc -l 
grep "StringC" server.log | wc -l 

Это длительный процесс, и мой сценарий занимает около 10 минут. Я хочу знать, может ли это быть оптимизировано или нет? Возможно ли запустить одну команду grep и узнать количество времени, когда StringA, StringB и StringC были вызваны индивидуально?

+2

Вы можете использовать 'grep -c' вместо' wc -l': 'grep -c 'StringA" server.log'. 'grep' не может сообщать количество отдельных строк. Вы можете использовать 'awk':' awk '/ StringA/{a ++;}/StringB/{b ++;}/StringC/{C++;} END {print a, b, c}' server.log'. –

+0

@ l3x Я собирался написать ответ, содержащий именно то, что вы написали в этом комментарии, а затем я увидел этот комментарий ... позаботьтесь, чтобы он стал ответом? –

+0

@BenjaminW. Я не хотел публиковать его, так как OP ищет «быстрое» решение. Я не был уверен, будет ли это достаточно быстро для него. Добавлено в любом случае. –

ответ

1

Конечно, этот подход может быть оптимизирован, так как grep не выполняет индексацию текста. Я бы использовал механизм индексации текста, например, один из них: this review или stackexchange QA. Также вы можете использовать journald из systemd, который хранит журналы в структурированном и индексированном формате, поэтому поисковые запросы более эффективны.

1

Так много greps так мало времени ... :-)

По David Lyness, прямой grep поиск примерно в 7 раз быстрее, чем в awk в больших поисках файлов.

Если это так, то нынешний подход может быть оптимизирован путем изменения grep к fgrep, но только если шаблонам разыскиваются являются не регулярных выражений. fgrep оптимизирован для фиксированных шаблонов.

Если количество экземпляров относительно невелико по сравнению с исходными записями файла журнала, это может быть улучшение использовать версию grepegrep создать временный файл, заполненный всеми тремя экземплярами:

egrep "StringA|StringB|StringC" server.log > tmp.log 
grep "StringA" tmp.log | wc -c 
grep "StringB" tmp.log | wc -c 
grep "StringC" tmp.log | wc -c 

Вариант egrepgrep позволяет использовать символ | (вертикальный бар/труба), который будет использоваться между двумя или более отдельными строками поиска, чтобы вы могли найти несколько строк в инструкции. Вы можете использовать grep -E, чтобы сделать то же самое.

Полная документация находится на странице man grep и информации о расширенных регулярных выражениях, которые egrep использует из команды man 7 re_format.

+0

Они не показывают количество отсчетов отдельно, которое ОП требует. –

+1

Спасибо за наблюдение, я действительно забыл о необходимости отдельных подсчетов. Я пересмотрел свой ответ, чтобы исправить это. –

+0

Тест 'awk' в David Lyness 'делает больше, чем просто подсчет матчей регулярных выражений. 'grep', вероятно, немного быстрее, но я сомневаюсь, что он на 7 раз быстрее, чем эквивалент' awk'. – chepner

3

Вы можете использовать grep -c вместо wc -l:

grep -c "StringA" server.log 

grep не может сообщить количество отдельных строк. Вы можете использовать AWK:

out=$(awk '/StringA/{a++;} /StringB/{b++;} /StringC/{c++;} END{print a, b, c}' server.log) 

Затем вы можете извлечь каждый подсчет с помощью простого массива:

arr=($out) 
echo "StringA="${arr[0]} 
echo "StringA="${arr[1]} 
echo "StringA="${arr[2]} 

Это (grep без wc), безусловно, будет быстрее и, возможно, awk решение также быстрее ,Но я не измерил.

+0

Я ожидал бы, что awk будет намного быстрее, потому что он проходит через файл только один раз, и три greps должны пройти через него три раза. –

Смежные вопросы