Shell Script – оптимизация Awk

Я ищу некоторую помощь в попытке оптимизировать сценарий синтаксического анализа лога сети, вот фон:

У меня большое количество журналов bro, но меня интересует только запрос IP-адресов в моей области (несколько подсетей переменной длины).

Поэтому у меня есть текстовый файл с шаблонами регулярных выражений в соответствии с диапазонами IP, которые я ищу: scope.txt:

/^10\.0\.0\.([8-9]|[1-3][0-9]|4[0-5])$/ 

(scope.txt содержит до 20 строк других диапазонов IP в шаблонах регулярных выражений) findInScope.sh:

 #!bin/sh for file in /data/bro_logs/2016-11-26/conn.*.log.gz do echo "$file" touch /tmp/$file for nets in $(cat scope.txt) do echo "$nets" zcat $file | bro-cut -d | awk '$3 ~ '$nets' || $5 ~ '$nets'' >> /tmp/$file done sort /tmp/$file | uniq > ~/$file rm /tmp/$file done 

Как больше фона, каждый час оригинальных журналов bro conn составляет около 100 МБ, поэтому мой текущий скрипт занимает около 10-20 минут, чтобы разобрать один час данных журнала. Один день бревна может занимать до 3 часов.

Я думал об одном утверждении awk с 40 или но решил, что я не хочу этого делать, потому что я хочу, чтобы отдельный файл scope.txt использовал тот же скрипт для разных областей IP-диапазонов.

Я также пробовал zcat в нескольких файлах conn.log (т. Е. Zcat conn. *. Log.gz), но выходной файл оказался более 1 ГБ, и я хотел сохранить часовые журналы без изменений.

  • Выходной сигнал в ловушке, вызвавший вызванную ловушку?
  • Блок условного исполнения с || и круглые скобки
  • Переменные за пределами цикла while
  • Является ли суб-оболочка той же самой, что и дочерняя оболочка
  • Разделить файлы с помощью awk и сгенерировать результаты в другом каталоге
  • zsh, модульность, несколько файлов .zsh и oh-my-zsh
  • Безопасно ли вводить другую команду в STDIN, пока предыдущая команда записывает в STDOUT?
  • Выполнять команды по отключению tmux
  • 2 Solutions collect form web for “Shell Script – оптимизация Awk”

    Вы должны получить много, передав файл журнала только один раз через awk. Это означает объединение всех регулярных выражений в один. Если вы не хотите делать это в своем файле scope.txt , сделайте это до вызова awk. Например,

     sed <scope.txt 's|^/\^|(|; s|\$/$|)|; $!s/$/|/' | tr -d '\n' >pattern zcat $file | bro-cut -d | awk ' BEGIN{ getline pat <"pattern"; pat = "^(" pat ")$" } $3 ~ pat || $5 ~ pat ' >~/$file 

    Сед заменяет /^ и $ окружающие каждую строку регулярного выражения с помощью вложенной () пары, добавляет | в конце строки и помещает результат на одной строке в pattern файла. Таким образом, этот файл содержит все шаблоны или-вместе. Отсутствующий ^(...)$ добавляется в операторе BEGIN скрипта awk, который читает файл шаблона в переменной pat .

    Вышеупомянутое заменяет ваш внутренний цикл for и sort|uniq .

    Самый простой ответ – использовать scope.txt , очень немного модифицированный, как шаблонный файл, и использовать zcat | grep zcat | grep (или просто zgrep ), чтобы получить zgrep строки.

    Сначала измените свой файл scope чтобы изменить:

     /^10\.0\.0\.([8-9]|[1-3][0-9]|4[0-5])$/ 

    в:

     (^|[^0-9.])(10\.0\.0\.([8-9]|[1-3][0-9]|4[0-5]))($|[^0-9.]) 

    Для этого вы можете использовать:

     sed -e 's:^/\^:(^|[^0-9.])(:' -e 's:\$/$:)($|[^0-9.]):' scope.txt > grepscope.txt 

    Затем выполните поиск:

     zgrep -Ehf grepscope.txt /data/bro_logs/2016-11-26/conn.*.log.gz | less 

    Или, поскольку вы хотите, чтобы выходные данные для каждого файла хранились отдельно:

     for f in /data/bro_logs/2016-11-26/conn.*.log.gz; do zgrep -Ehf grepscope.txt "$f" | sort -u > ~/"${f##*/}" done 

    Заметим также, что переменная цикла «for» $f будет содержать весь путь к каждому файлу по очереди; чтобы избежать ошибок, которые мы получили бы, если бы мы попытались направить вывод в ~/"$f" (который будет ссылаться на подкаталоги ~/data/bro_logs/2016-11-26 которые, вероятно, не существуют в вашем домашнем каталоге), мы отмените все до последней косой черты в имени пути и просто используйте базовое имя каждого файла журнала.


    Флаги для zgrep несут упоминание:

    -E указывает расширенное регулярное выражение, так что скобки в ваших шаблонах не должны быть экранированы.

    -h подавляет печать имени файла в качестве префикса для каждой соответствующей строки. (Вы можете опустить это в версии цикла for , так как по умолчанию grep печатает только имя файла при поиске более одного файла, как и в первой заданной мной команде, но ничего не мешает сохранить в обеих версиях.)

    -f позволяет указать шаблонный файл. Это то, что вам нужно, в соответствии с вашим вопросом, и использование grep -f позволяет использовать несколько шаблонов поиска, взятых из файла, без создания команды Awk с огромным количеством «или».


    sort | uniq sort | uniq обычно можно заменить на sort -u , если вам не нужно использовать некоторые флаги параметров uniq . В этом случае вы этого не сделаете, поэтому я использовал более простой вид sort -u .

    Interesting Posts
    Linux и Unix - лучшая ОС в мире.