GREP exclui os primeiros 11 valores

2

Eu tenho um arquivo de log enorme que preciso filtrar. Neste log, quero exibir todos os logs que contêm a string dns e quero vê-los apenas uma vez.

ou seja, a partir disso:

Dec  9 07:24:02 94.15.218.140 syslog: ssk:548.049:is_dns_hijack:1451:isDnsHijack=0
Dec  9 07:24:10 90.192.172.112 syslog: ssk:363.217:cmsLck_acquireLockWithTimeoutTraced:98:acquired lock. callerFuncName is_dns_hijack; timeout 12000 milliseconds
Dec  9 07:24:10 90.192.172.112 syslog: ssk:363.218:cmsLck_releaseLockTraced:144:lock hold time=0ms, acquiring lock callerFuncName is_dns_hijack; releasing lock callerFuncName is_dns_hijack;
Dec  9 07:24:10 90.192.172.112 syslog: ssk:363.225:is_dns_hijack:1425:isDnsHijack=0
Dec  9 07:24:17 94.15.218.140 syslog: ssk:563.048:cmsLck_acquireLockWithTimeoutTraced:95:acquired lock. callerFuncName is_dns_hijack; timeout 12000 milliseconds
Dec  9 07:24:17 94.15.218.140 syslog: ssk:563.048:cmsLck_releaseLockTraced:141:lock hold time=0ms, acquiring lock callerFuncName is_dns_hijack; releasing lock callerFuncName is_dns_hijack;
Dec  9 07:24:17 94.15.218.140 syslog: ssk:563.049:is_dns_hijack:1451:isDnsHijack=0

para isso:

Dec  9 07:24:02 94.15.218.140 syslog: ssk:548.049:is_dns_hijack:1451:isDnsHijack=0
Dec  9 07:24:10 90.192.172.112 syslog: ssk:363.217:cmsLck_acquireLockWithTimeoutTraced:98:acquired lock. callerFuncName is_dns_hijack; timeout 12000 milliseconds
Dec  9 07:24:10 90.192.172.112 syslog: ssk:363.218:cmsLck_releaseLockTraced:144:lock hold time=0ms, acquiring lock callerFuncName is_dns_hijack; releasing lock callerFuncName is_dns_hijack;

Basicamente, é o mesmo log repetido mais vezes devido a um timestamp diferente.

Eu estava tentando usar uniq , mas para isso eu preciso remover o registro de data e hora na terceira coluna (alcançável com awk '{ $3=""; print }' ), mas como você pode ver no log, os primeiros 11 caracteres são diferentes (ou seja, ssk:563.048 - ssk:563.049 ). Eu estava pensando em fazer um grep com a palavra dns e tentando ignorar os primeiros 11 valores.

Como posso fazer isso? Existe uma maneira melhor?

    
por Federi 09.12.2015 / 12:46

1 resposta

3

Use awk e : como o delimitador de campo. Em seguida, você pode salvar cada mensagem de erro exclusiva (que será o sexto campo) em uma matriz e imprimir somente a primeira ocorrência:

$ awk -F: '!a[$6]++' file 
Dec  9 07:24:02 94.15.218.140 syslog: ssk:548.049:is_dns_hijack:1451:isDnsHijack=0
Dec  9 07:24:10 90.192.172.112 syslog: ssk:363.218:cmsLck_releaseLockTraced:144:lock hold time=0ms, acquiring lock callerFuncName is_dns_hijack; releasing lock callerFuncName is_dns_hijack;
Dec  9 07:24:10 90.192.172.112 syslog: ssk:363.217:cmsLck_acquireLockWithTimeoutTraced:98:acquired lock. callerFuncName is_dns_hijack; timeout 12000 milliseconds

O script acima salvará cada linha como uma entrada na matriz associativa a somente se ainda não houver um valor salvo para o 6º campo ( !a[$6] ). Como a ação padrão em awk é imprimir quando algo é avaliado como true, isso resultará apenas nas primeiras ocorrências exclusivas sendo impressas.

Se você quiser fazer isso apenas para linhas que correspondam a dns , use:

awk -F: '!a[$6]++ && /dns/' file 

Quanto a ignorar as 11 primeiras linhas, você pode fazer isso com:

grep dns file | tail -n +12
    
por 09.12.2015 / 12:55