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 ГБ, и я хотел сохранить часовые журналы без изменений.

  • Загрузите файл на сервер?
  • Возможно ли, чтобы переменные bash сохранялись между прогонами
  • Скрипт оболочки Gnuplot
  • Ответ yes в сценарии bash
  • Как вычислить имя файла эскиза из оболочки?
  • case + как реализовать равный или меньше или больше в случае синтаксиса
  • Выполнить команду после inotifywait установленных часов
  • Режим Vi или режим emacs во всей системе
  • 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

    Ошибка с командой make и sudo make install в терминале

    Какая версия NFS используется моим сервером NFS?

    выйти из окна tmux без выхода из программы терминала

    Сделать Bluetooth-устройство невидимым / отключить входящее соединение

    Магический номер для новой файловой системы

    Определите порт USB, к которому подключен мобильный телефон?

    Запись «grub» в BIOS после установки ElementaryOS

    Можете ли вы установить OpenVPN для автоматического подключения к «резервному» .ovpns в случае, если текущий не удается?

    passwd не работает после изменения CRYPT_DEFAULT

    Распечатайте n строк до и m строк после совпадения с pdfgrep

    Использование пакета Debian на основе хрома

    Конфигурация установки Apache не может найти PCRE? (pcre-config для libpcre не найден)

    Как использовать Super-L вместо Alt в XFCE для изменения размера / перемещения окон?

    Проверьте пароль пользователя с помощью сценария оболочки

    вкладки при использовании 'screen'

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