encontra o arquivo de log correto de milhares usando head e fgrep

0

Eu tenho milhares de arquivos de log - todos muito grandes. Um deles terá um endereço IP que estou procurando. Eu sei que é muito provável que ocorra perto do topo do arquivo. Eu posso fazer:

head -n 500 *.log | fgrep myip

e eu vou ver que "sim", está em um dos arquivos de log. Como faço para determinar qual deles? Não é possível obter o conteúdo completo (fgrep myip * .log) de todos os arquivos devido ao seu tamanho.

    
por PaulN 12.06.2018 / 00:04

4 respostas

0

Algo como isso deve ajudar.

find . -iname "*.log" -print0 | xargs -0 -i{} bash -c 'echo "»»»File Name: {}«««"; head -n 500 {} | fgrep -B 501 myip'

Ele produzirá uma longa lista de nomes de arquivos e, em seguida, até 500 linhas de dados encontrados, em seguida, uma longa lista de nomes de arquivos. O nome do arquivo que você deseja é o imediatamente anterior à longa lista de dados.

    
por 12.06.2018 / 00:25
1

Você pode se safar com o awk:

awk -v ip=127.0.0.1 'substr($0, ip) > 0 {print FILENAME ": " $0} FNR > 500 {nextfile}' *.log

Se o IP foi encontrado na linha atual, nós o imprimimos e o nome do arquivo. Passamos para o próximo arquivo se o número da linha atual do arquivo atual ( FNR ) se tornar > 500.

    
por 12.06.2018 / 11:35
0
find -name \*.log -print0 |
  xargs -0 sh -c 'for i; do head -n 500 $i | fgrep -q myip && echo $i; done

Isso localizará todos os nomes de arquivos terminados em .log e alimentará essa lista em xargs . Os -print0 e xargs -0 são comumente usados para usar um byte nulo para finalizar os nomes dos arquivos, para proteger nomes de arquivos que contêm espaços (um byte nulo nunca pode ser usado em um nome de arquivo, portanto, é um delimitador seguro).

xargs executará o comando dado após xargs e seus argumentos com tantos nomes de arquivos quantos couberem em uma chamada do comando. Neste caso, o comando dado é sh (o shell), e este shell recebe um pequeno script de shell para ser executado.

O script de shell é basicamente:

for i; do
    head -n 500 $i | fgrep -q myip && echo $i
done

A parte for i faz um loop sobre todos os argumentos dados ao shell, ou seja, todos os nomes de arquivos. Para cada nome de arquivo, são necessárias as primeiras 500 linhas e a busca pela string dada. fgrep -q significa que o fgrep pára assim que a string é encontrada; se a string for encontrada, um status de saída "sucesso" será fornecido, caso contrário, "falhará". Finalmente, o && echo $i significa que, se o comando anterior tiver um status de "sucesso", o eco será executado, o que significa que o nome do arquivo será mostrado se a string for encontrada.

    
por 12.06.2018 / 11:16
0

Eu gostaria de:

  1. faça um loop sobre todos os arquivos
  2. pegue as primeiras 500 linhas
  3. veja se o IP está nessas linhas
  4. se for o caso, imprima o nome do arquivo e finalize o loop

como código:

for f in ./*
do 
  head -n 500 "$f" | grep -qF myip && { printf "Found in: $f"; break; }
done

Onde você substitui myip pelo IP que está procurando. Você poderia criar uma função (ou shell script) que pega o IP desejado como parâmetro para procurar:

findlogip ()
{
    for f in ./*;
    do
        head -n 500 "$f" | grep -qF "$1" && {
            printf "Found in: $f\n";
            break
        };
    done
}

Como roaima comentou , você pode querer ter cuidado com o IP que está procurando para não coincidir acidentalmente com um IP diferente (10.55.33.6, mas correspondendo a 110.55.33.68 no exemplo). Com o GNU grep (assumido, dada a tag ), você pode cercar endereço IP fornecido com \b marcadores:

...
head -n 500 "$f" | grep -q "\b$1\b" && ...
...

Você solta a opção -F (string fixa) do grep, pois a expressão não é mais uma expressão "fixa", mas uma expressão regular.

    
por 13.06.2018 / 18:47

Tags