Предполагая, что ваши строки журнала также -сформированы, как предполагает фрагмент, это было бы началом:
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
запуска был добавлен, а не перезаписан.
Таким образом, ваша текущая логика такова: «Для каждой строки в 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