Я предполагаю, что вы делаете это в цикле оболочки по всем IP-адресам, возможно, с IP-адресами, полученными из текстового файла. Да, это было бы медленно, с одним вызовом sed
или grep
для каждого IP-адреса.
Вместо этого вам может сойти с рук однократное использование sed
, если вы тщательно подготовитесь.
Во-первых, мы должны создать скрипт sed
, и мы делаем это из файла ip.list
, который содержит IP-адреса, по одному адресу в строке:
sed -e 'h' \
-e 's/\./\\./g' \
-e 's#.*#/^&[[:blank:]]/w /tmp/access-#' \
-e 'G' \
-e 's/\n//' \
-e 's/$/.log/' ip.list >ip.sed
Этот sed
материал делает для каждого IP-адреса
sed
). .
в «пространстве шаблона» (строку ввода )на \.
(, чтобы правильно сопоставить точки, ваш код этого не сделал ). ^
и добавить [[:blank:]]/w /tmp/access-
к пространству шаблонов. .log
в конец строки (и неявно выведите результат ). Для файла, содержащего
127.0.0.1
10.0.0.1
10.0.0.100
это создаст sed
скрипт
/^127\.0\.0\.1[[:blank:]]/w /tmp/access-127.0.0.1.log
/^10\.0\.0\.1[[:blank:]]/w /tmp/access-10.0.0.1.log
/^10\.0\.0\.100[[:blank:]]/w /tmp/access-10.0.0.100.log
Обратите внимание, что после IP-адреса вам нужно будет поставить пробел (, пробел или табуляцию ), иначе записи журнала для 10.0.0.100
попадут в файл /tmp/access-10.0.0.1.log
. В вашем коде это пропущено.
Затем это можно использовать в файле журнала (без циклов):
sed -n -f ip.sed /var/log/http/access.log
Я никогда не тестировал запись в 1200 файлов из одного и того же sed
скрипта. Если это не сработает, попробуйте приведенный ниже вариант awk
.
Аналогичное решение с awk
предполагает сначала чтение IP-адресов в массив, а затем сопоставление их с каждой строкой. Для этого требуется один единственный awk
вызов:
awk 'FNR == NR { list[$1] = 1; next }
$1 in list { name = $1 ".log"; print >>name; close name }' ip.list /var/log/http/access.log
Здесь мы даем awk
и список IP-адресов, и файл журнала одновременно. Когда NR == FNR
мы знаем, что мы все еще читаем первый файл (список ), мы добавляем IP-номера в ассоциативный массив list
в качестве ключей и продолжаем со следующей строки ввода.
Если условие FNR == NR
не верно, мы читаем из второго файла (лог-файл )и проверяем, является ли самое первое поле входной строки ключом вlist
(этом это простое сравнение строк, а не совпадение с регулярным выражением ). Если это,мы добавляем строку в файл с соответствующим именем.
Мы должны быть осторожны с закрытием выходного файла, так как в противном случае у нас могут закончиться дескрипторы открытых файлов. Таким образом, будет много открытий и закрытий файлов для добавления, но это все равно будет быстрее, чем вызовawk
(или любой утилиты )один раз для каждого IP-адреса.
Мне было бы интересно узнать, работают ли эти вещи для вас и каково приблизительное время работы. Я тестировал решения только на очень малых наборах данных.
Конечно, мы могли бы согласиться с вашей идеей просто переборщить, выбрасывая несколько экземпляров, например. grep
в системе параллельно:
Игнорируя тот факт, что мы неправильно сопоставляем точки в IP-адресах, мы могли бы получить что-то вроде
xargs -P 4 -n 100 sh -c '
for n do
grep "^$n[[:blank:]]" /var/log/http/access.log >"/tmp/access-$n.log"
done' sh <ip.list
Здесь xargs
даст не более 100 IP-адресов за раз из файла ip.list
короткому сценарию оболочки. Это устроит четыре параллельных вызова скрипта.
Короткий сценарий оболочки:
for n do
grep "^$n[[:blank:]]" /var/log/http/access.log >"/tmp/access-$n.log"
done
Это будет просто перебирать 100 IP-адресов, которые xargs
дает ему в своей командной строке, и применять почти ту же команду grep
, что и у вас, разница в том, что будет четыре из этих циклов, работающих в параллельно.
Увеличьте -P 4
до -P 16
или что-то, связанное с количеством процессоров, которые у вас есть. Ускорение, вероятно, не будет линейным, так как каждый параллельный экземпляр grep
будет читать и записывать на один и тот же диск.
За исключением флага -P
для xargs
, все вещи в этом ответе должны работать в любой системе POSIX. Флаг -P
для xargs
не является стандартом -, но реализован в GNU xargs
и в системах BSD.
Это не ответит на ваш вопрос, как указано, но должно помочь вам разобраться с основным сценарием.
Традиционное решение, когда вам нужен источник пакетов с неизменяющимися версиями, это использовать частные репозитории пакетов :, отражающие репозитории выбранного вами дистрибутива, а затем оставить их как есть -, только изменяя пакеты по частям. Последняя часть является болезненным компонентом для тестирования, потому что разные сценарии тестирования часто требуют разных обновлений пакетов по сравнению с общим базовым репозиторием, и тогда вам приходится поддерживать несколько репозиториев...
Контейнеры предлагают гораздо более простое решение в сочетании с реестрами образов. Создайте базовый тестовый образ, как обычно, со всеми вашими тестовыми зависимостями :
.FROM debian:10
RUN apt update && apt upgrade && apt install...
Соберите это и загрузите в свой (частный )реестр с соответствующим тегом (датой, если не лучше ). Тогда ваши тестовые сценарии могут быть основаны на этом образе, который не изменится. Когда вы решите, что вам нужно обновить определенный пакет, используйте новый образ с соответствующей зависимостью от вашего базового образа :
.FROM testbase:20200229
RUN apt update && apt install...
список только тех пакетов, которые вы хотите обновить (или установить ); Таким образом, будут обновлены только эти пакеты, если только они не потребуют более нового пакета в своих собственных зависимостях, и в этом случае он тоже будет загружен (, но нет простого способа избежать этого, поэтому вы все равно придется иметь с этим дело ).
Базовый тестовый образ можно перестраивать и отправлять через равные промежутки времени, не затрагивая существующие тесты, если последние ссылаются на соответствующий тегированный образ.
Зависимости объявлены, потому что тот, кто упаковывал вещи, определил, что они нужны, в указанных версиях. Конечно, они могут переусердствовать, запрашивая ненужные вещи или запрашивая новые версии, когда старые работают нормально. Но проверка каждого возможного сценария требует много работы, у упаковщиков ограниченное время. Когда это разумно, они будут иметь форму «версия xyz не ниже 5.3», и она должна работать с любой более поздней версией.
Если вы не установите запрошенные зависимости, вы забредете на совершенно непроверенную территорию. Он может нормально работать, загадочным образом ломаться или просто взорваться вам в лицо.