Баш пока ОЧЕНЬ медленный - PullRequest
0 голосов
/ 19 ноября 2018

У меня есть цикл while, который читает файл журнала почты и помещает его в массив, так что я смогу искать в массиве и сопоставлять / искать поток. К сожалению, цикл while требует много времени, чтобы пройти через файл, это очень большой файл, но должен быть другой более быстрый способ сделать это.

cat /home/maillog |grep "Nov 13" |grep "from=<xxxx@xxxx.com>" |awk '{print $6}' > /home/output_1 

while read line; do awk -v line="$line" '$6 ~ line { print $0 }' /home/maillog >> /home/output_2 ; done < /home/output_1

Есть идеи? Спасибо заранее.

1 Ответ

0 голосов
/ 19 ноября 2018

Давайте проанализируем ваш сценарий и попытаемся объяснить, почему он работает медленно.

Давайте начнем с микрооптимизации вашей первой строки. Это не собирается ускорять вещи, но это просто образовательный процесс.

cat /home/maillog |grep "Nov 13" |grep "from=<xxxx@xxxx.com>" |awk '{print $6}' > /home/output_1 

В этой строке вы совершаете 4 вызова в разные двоичные файлы, которые в итоге могут быть выполнены одним. Для удобства чтения вы можете оставить эту строку. Тем не менее, вот два основных момента:

  1. Бесполезное использование cat. Программа cat в основном используется для конкатенации файлов. Если вы просто добавите один файл, то это в основном излишне. Особенно, если вы хотите передать его grep.

    cat file | grep ... => grep ... file
    
  2. несколько greps в сочетании с awk ... можно записать как один awk

    awk '/Nov 13/ && /from=<xxxx@xxxx.com>/ {print $6}'
    

Таким образом, вся строка может быть записана как:

awk '/Nov 13/ && /from=<xxxx@xxxx.com>/ {print $6}' /home/maillog > /home/output_1

Во второй части все идет медленно:

while read line; do 
   awk -v line="$line" '$6 ~ line { print $0 }' /home/maillog >> /home/output_2 ;
done < /home/output_1

Почему это медленно? В каждой строке вы читаете форму /home/output_1, загружаете программу awk в память, открываете файл /home/maillog, обрабатываете каждую его строку и закрываете файл /home/maillog. В то же время для каждой обрабатываемой строки вы каждый раз открываете /home/output_2, помещаете указатель файла в конец файла, записываете в файл и снова закрываете файл.

Вся программа фактически может быть выполнена с помощью одного awk:

awk '(NR==FNR) && /Nov 13/ && /from=<xxxx@xxxx.com>/ {a[$6];next}($6 in a)' /home/maillog /home/maillog > /home/output2
...