Salim Aouar - ensinando para transformar!

Shell Scripting para Análise de Log do Squid

O dia que bati recorde em tempo de execução com Shell Script!

Por Salim Aouar dia em GNU/Linux

Shell Scripting para Análise de Log do Squid
  • Compartilhe esse post
  • Compartilhar no Facebook00
  • Compartilhar no Google Plus00
  • Compartilhar no Twitter

Encontrei um script shell muiiiito bacana aqui. Eu o escrevi no ano de 2008, quando fazia minha especialização em Administração de Redes GNU/Linux, pela Universidade Federal de Lavras (UFLA).

O professor havia passado um arquivo de log do squid muito grande. Não me lembro certamente, mas sei que tinham mais de 4GB somente de texto. E ele pediu para que fizéssemos um script shell para analisar aquele 'pequeno' arquivo: Fazer um ranking dos 10 IPs que mais consumiram dados em um data específica.

Por exemplo, eu chamaria o script da seguinte forma na linha de comandos e ele me retornaria a lista dos 10 IPs locais que consumiram mais banda (em ordem decrescente): ./meuscript.sh 20180606 /var/log/squid3/access.log

Cada linha do arquivo de log corresponde a um registro de acesso através do Squid. Está aqui um exemplo com 5 linhas:

1528362727.333 47 192.168.1.2 TCP_MISS/200 1757 GET http://cdn.content.prod.cms.msn.com/singletile/summary/alias/experiencebyname/today? - ORIGINAL_DST/2.21.178.106 text/xml
1528362727.333 46 192.168.1.2 TCP_MISS/200 1666 GET http://cdn.content.prod.cms.msn.com/singletile/summary/alias/experiencebyname/today? - ORIGINAL_DST/2.21.178.106 text/xml
1528362871.930 68 192.168.1.2 TCP_MISS/200 245 GET http://ncc.avast.com/ncc.txt - ORIGINAL_DST/200.143.247.16 text/html
1528363182.538 896988 192.168.1.2 TCP_MISS/200 311 GET http://su.ff.avast.com/R/A3kKIDQ0NzhlNGNhNjE4MzQyNmNiMDQ2YWI1ZTRkZThlMjhkEgQABwYYGLwHIgECKgcIBBCmpOVgKgcIAxCo14ZdMgoIABDFq-VgGIACOKKSkJABQiCTz0gZi7kd90OW8GIZphTR4939b-VE5k2JfgQW7Y5QAUiAgpgI - ORIGINAL_DST/77.234.42.239 application/octet-stream
1528363472.061 74 192.168.1.2 TCP_MISS/200 245 GET http://ncc.avast.com/ncc.txt - ORIGINAL_DST/200.143.247.16 text/html

Perceba que cada campo corresponde a uma informação, você pode ver os detalhes aqui sobre elas. Mas, as principais para o script eram: o Timestamp para pegar a data (1º campo), o IP do host local (3º campo), e a quantidade de Bytes consumida por aquela requisição (2º campo).

Na época fiz um primeiro script que utilizava 'loop dentro de loop' (complexidade quadrática), ou seja, eu varria o arquivo diversas vezes para fazer a soma dos Bytes para cada IP encontrado. Gerou um tempo de execução que ultrapassou os 10 minutos!

Foi quando utilizei o 'awk' (que é uma linguagem interpretada, muito utilizada para processamento de dados em arquivos de texto) e, além disso, utilizei Array Associativo. Enfim... eu tinha que varrer o arquivo apenas 1 vez, e concatenar os valores dos Bytes ao meu array que tinha como índice o IP do host.

Após essas modificações, o script passou a executar com menos de 2 segundos. Uma grande diferença, de 10 minutos para 2 segundos, não é mesmo?!

Vamos ao script... a parte inicial dele é toda de validação de formatos. O interessante está no final, quando é utilizado o AWK:

#!/bin/bash
#por Salim Aouar

#Validação de quantidade de parâmetros
if [ $# != 2 ]; then
echo "erro 001 - Número incorreto de parâmetros (./script aaaammdd arquivoLog)"
exit 1
fi

#Validação de existência de arquivo com log
if [ ! -f $2 ]; then
echo "erro 002 - $2 não é um arquivo válido"
exit 2
fi

#Validação de permissão de leitura no arquivo de log
if [ ! -r $2 ]; then
echo "erro 003 - Não se tem permissão de leitura em $2"
exit 3
fi

#Validação da data digitada pelo usuário, utilizando expressão regular
data=$(echo $1 | egrep '^([0-9]{8})')
if [ -z $data ]; then
echo "erro 004 - Formato da data inválido (./script aaaammdd arquivoLog)"
exit 4
fi

#Separando a data em ano, mês e dia
a=$(echo $data | cut -c1-4)
m=$(echo $data | cut -c5-6)
d=$(echo $data | cut -c7-8)

#Definindo os timestamps para o início e fim, pois serão comparados
dataInicial=$(date -d "$a-$m-$d" "+%s")
dataFinal=$(date -d "$a-$m-$d 23:59:59" "+%s")

#awk imprimindo o cabeçalho, somando os Bytes utilizando array associativo e, imprimindo o ranking
awk -F" " '
BEGIN {
print "IP\t\tCONSUMO"
}
{
if($1 >= '$dataInicial' && $1 <= '$dataFinal')
consumos[$3] += $2
}
END {
for (x in consumos)
print x"\t"consumos[x] | "sort -k2 -nr | head"
}
' $2

Vou destacar aqui apenas 2 trechos deste script para fins de explicação. O primeiro deles é referente a soma dos Bytes consumidos e ligando ao IP no Array:

if($1 >= '$dataInicial' && $1 <= '$dataFinal')
consumos[$3] += $2
}

Repare acima que estamos verificando se o Timestamp do arquivo de log (1º campo - $1) está dentro da data desejada e, caso esteja, acumulamos a soma dos Números de Bytes (2º campo - $2) no nosso vetor, cujo índice/posição é o número do IP do Host (3º campo - $3). Dessa forma, quando terminamos de percorrer todo o arquivo, temos um vetor com vários IPs de índices e seus respectivos consumos em Bytes salvos.

Aí podemos mandar exibir na tela os 10 IPs que mais consumiram dados. Fazendo um loop para percorrer nosso array 'consumos':

for (x in consumos)
print x"\t"consumos[x] | "sort -k2 -nr | head"
}

Aí vem mais um detalhe... no trecho 'sort -k2 -nr | head' estamos pedindo para ordenar pelo segundo campo que é numérico (comando sort), e depois chamamos o 'head' para exibir somente os 10 primeiros da lista!

Enfim... neste script aí tem muita informação bacana, que você pode estudar e testar! Veja as partes de validações de data, parâmetros, etc... isto é muito importante também!

Gostaria de enfatizar que como bons profissionais, devemos sempre estudar e procurar aperfeiçoamento. Já escutei muitos falarem que vão trabalhar com redes ou servidores, pois não gostam de programação, e vice-versa. Entretanto, saibamos reconhecer que as áreas não são isoladas, e devemos sempre pensar de forma integrada!

- E como aprender bem a programar em Shell Script??? Resposta: Inicie aprendendo a usar bem os comandos no GNU/Linux. Pratique os comandos, entenda os usos e finalidades. Já será um excelente começo!

Faça o download do meu Guia de Bolso com Comandos GNU/Linux!!!

E o que você achou do script?! Acha que devemos pensar em integração?! Deixe abaixo seu comentário. Além disso, ajude-me a levar conhecimento de qualidade ao maior número de pessoas interessadas, compartilhe este artigo em suas redes sociais!!!

Estou sempre disposto a produzir materiais e ensino de qualidade! Vamos juntos nesta jornada!!!

Abraços,
Salim Aouar.

  • Compartilhe esse post
  • Compartilhar no Facebook00
  • Compartilhar no Google Plus00
  • Compartilhar no Twitter

Deixe seu comentário aqui: