как повысить производительность cat и xargs в сценарии bash

Предполагая, что ваши строки журнала также -сформированы, как предполагает фрагмент, это было бы началом:

awk '{
      dir=$1 "/" $2; log_file=dir "/" substr($3, 1, 2) ".log"
      if (!exists[dir]++) {system("mkdir -p " dir)}; 
      print > log_file
}' amp.log

Вы должны выполнить это в /var/log/mail_logs/.

Вызов systemвнешней команды mkdirсоздает конкретный каталог даты -, если он не существует. Передача -pприводит к тому, что родители создаются по мере необходимости (, поэтому каталог Octсоздается, когда mkdir -p /Oct/01впервые запускает October ). Кроме того, -pгарантирует, что mkdirне сообщит об ошибке, если каталог уже существует.

Вызов printзаписывает строки журнала в файл, имя которого создается из компонентов времени журнала. Каждый новый файл журнала создается при первой записи и дополняется в течение времени существования команды.

Вы можете изменить print >на print >>, если хотите, чтобы файл журнала на основе даты и времени -из предыдущего awkзапуска был добавлен, а не перезаписан.

1
14.05.2021, 03:12
1 ответ

Таким образом, ваша текущая логика такова: «Для каждой строки в 1m.txt проверьте, не находится ли она уже в файле advance.txt. Если нет, обработайте ее и добавьте в файл out.txt. Когда задание запущено, обновите файл advance.txt с помощью все строки в out.txt'.

Проблема заключается в том, что чем больше строк добавляется в файл advance.txt, тем больше строк приходится сравнивать каждой строке. В худшем случае, если каждая строка была обработана, необходимо будет проверить каждую из миллионов строк в файле 1m.txt, чтобы убедиться, что она находится в файле advance.txt. В среднем вам нужно сравнить половину строк в файле advance.txt, поэтому для этого потребуется 1 000 000 *500 000 или 500 000 000 000 (500 миллиардов )сравнений.

Если бы вы не обрабатывали вещи параллельно, прямым способом справиться с этим было бы найти последнюю строку в out.txt и пропустить все строки в 1m.txt до этой точки. например.

# Pipe the output of the if/then/else/fi construct to xargs.
# use the if/then/else/fi to select the input.
# Use '-s' to see if the file exists and has non zero size.
 if [ -s out.txt ] ; then
    # we have some existing data
    # Get the host from the last line
    # delete anything that is not the last line
    # remove the DIE/OK. quote anything not alphabetic with a backslash.
   lasthost="$(sed '$!d;s/^\(DIE\|OK\) //;s/[^0-9a-zA-Z]/\\&/g' out.txt)"
   # get the lines from 1m.txt from after the matched host
   # uses GNU sed extension to start at line "0"
   sed "0,/^$lasthost\$/d" 1m.txt
 else
   # no existing data, so just copy the 1m.txt using cat
   cat 1m.txt
 fi | xargs -I {} sh -c "if host {} >/dev/null; then echo OK {}; else echo DIE {}; fi" >> out.txt

Однако вы обрабатываете вещи параллельно. Поскольку для возврата значения hostможет потребоваться очень различное количество времени, входные данные могут быть значительно изменены. Необходим более быстрый способ узнать, был ли хост уже замечен. Стандартным способом является использование какой-либо хеш-таблицы. Один из способов — использовать awk.

 if [ -s out.txt ] ; then
    # we have some existing data. Process the two files given
    # for the first file set the entries of the seen array to 1
    # for the second file print out the hosts which have not been seen. 
    awk 'FNR==NR {seen[$2]=1;next} seen[$1]!=1' out.txt 1m.txt
 else
   cat 1m.txt
 fi | xargs -I {} -P 100 sh -c "if host {} >/dev/null; then echo OK {}; else echo DIE {}; fi" >> out.txt
1
28.07.2021, 11:32

Теги

Похожие вопросы