Eu gostaria de analisar os IPs wrt do log de acesso do apache. Eu usei o código a seguir, mas demorou quase 90 segundos.
grep "^$CLIENT_IP" /var/log/http/access.log > /tmp/access-$CLIENT_IP.log
Então eu tentei alternativa como abaixo.
sed -i -e "/^$CLIENT_IP/w /tmp/access-$CLIENT_IP.log" -e '//d' /var/log/http/access.log
mesmo isso levou mais de 60 segundos também.
Existem 1200 IPs para analisar. Gostaria de saber se existe alguma maneira de implementar o paralelismo para reduzir o tempo de execução.
Estou assumindo que você está fazendo isso em um loop de shell em todos os endereços IP, possivelmente com os endereços IP provenientes de um arquivo de texto. Sim, isso seria lento, com uma invocação de
sed
ougrep
por endereço IP.Em vez disso, você pode se safar com um único uso de
sed
, se se preparar com cuidado.Primeiro temos que criar um
sed
script, e fazemos isso a partir de um arquivoip.list
que contém os endereços IP, um endereço por linha:Este
sed
material faz, para cada endereço IP,sed
)..
o "espaço padrão" (a linha de entrada) para\.
(para corresponder aos pontos corretamente, seu código não fez isso).^
e anexar[[:blank:]]/w /tmp/access-
ao espaço padrão..log
ao final da linha (e imprima implicitamente o resultado).Para um arquivo que contém
isso criaria o
sed
scriptObserve que você terá que corresponder a um caractere em branco (espaço ou tabulação) após o endereço IP, caso contrário, as entradas de log
10.0.0.100
irão para o/tmp/access-10.0.0.1.log
arquivo. Seu código omitiu isso.Isso pode ser usado em seu arquivo de log (sem loop):
Nunca testei a gravação em 1200 arquivos de um único e mesmo
sed
script. Se não funcionar, tente aawk
variação abaixo.Uma solução semelhante
awk
envolve primeiro ler os endereços IP em uma matriz e, em seguida, compará-los com cada linha. Isso requer uma únicaawk
invocação:Aqui, fornecemos
awk
a lista de IP e o arquivo de log ao mesmo tempo. QuandoNR == FNR
sabemos que ainda estamos lendo o primeiro arquivo (a lista), adicionamos os números IP na matriz associativalist
como chaves e continuamos com a próxima linha de entrada.Se a
FNR == NR
condição não for verdadeira, estamos lendo do segundo arquivo (o arquivo de log) e testamos se o primeiro campo da linha de entrada é uma chavelist
(esta é uma comparação de string simples, não uma correspondência de expressão regular) . Se for, anexamos a linha ao arquivo nomeado apropriadamente.Devemos ter cuidado ao fechar o arquivo de saída, caso contrário, podemos ficar sem descritores de arquivo aberto. Portanto, haverá muitos arquivos abrindo e fechando para anexar, mas ainda será mais rápido do que chamar
awk
(ou qualquer utilitário) uma vez por endereço IP.Eu estaria interessado em saber se essas coisas funcionam para você e qual pode ser o tempo de execução aproximado. Testei as soluções apenas em conjuntos de dados extremamente pequenos.
Claro, poderíamos seguir sua ideia de apenas força bruta, lançando várias instâncias de, por exemplo
grep
, no sistema em paralelo:Ignorando o fato de que não combinamos os pontos nos endereços IP corretamente, podemos fazer algo como
Aqui,
xargs
fornecerá no máximo 100 endereços IP por vez doip.list
arquivo para um script de shell curto. Ele providenciará quatro invocações paralelas do script.O script de shell curto:
Isso apenas iterará sobre os 100 endereços IP fornecidos
xargs
em sua linha de comando e aplicará praticamente o mesmogrep
comando que você tinha, a diferença é que haverá quatro desses loops executando em paralelo.Aumente
-P 4
para-P 16
ou algo relacionado ao número de CPUs que você possui. A aceleração provavelmente não seria linear, pois cada instância paralela degrep
leria e gravaria no mesmo disco.Exceto pelo
-P
sinalizador paraxargs
, todas as coisas nesta resposta devem poder ser executadas em qualquer sistema POSIX. O-P
sinalizador paraxargs
não é padrão, mas implementado em sistemas GNUxargs
e BSD.Para várias abordagens: https://stackoverflow.com/questions/9066609/fastest-possible-grep
Além disso, se você está fazendo muito isso, um SSD provavelmente é o caminho a percorrer. Tocar no HD é o assassino para algo assim.
Você tem um grande número de greps diferentes para executar. Crie um script que inicie comandos de script (digamos, um por núcleo) em segundo plano e, em seguida, rastreie quando eles terminarem, conforme forem concluídos, inicie mais.
Quando eu estava fazendo isso, consegui que todos os 12 núcleos rodassem com 100% de uso da CPU, mas você pode descobrir que seu limite de recursos é outra coisa. Dado que todos os seus trabalhos desejam o mesmo arquivo, se você não estiver em um SSD, convém copiar esse arquivo para que não sejam compartilhados.
Se
/var/log/http/access.log
for maior que a RAM e, portanto, não puder ser armazenado em cache, executar mais processos em paralelo pode ser uma boa alternativa para leraccess.log
várias vezes - especialmente se você tiver vários núcleos. Isso executará umgrep
por IP em paralelo (+ alguns processos de empacotamento de ajuda).