Filtrando datas com grep e awk

3

Eu criei o alias abaixo no meu arquivo .bash_aliases

alias auth="grep \"$(date|awk '{print $2,$3}')\" /var/log/auth.log |
            grep -E '(BREAK-IN|Invalid user|Failed|refused|su|Illegal)'"

Isso deve:

  • verifique a data de hoje
  • grep auth.log para mensagens de hoje
  • grep mensagens de hoje para mensagens de aviso que correspondem a cadeias específicas

No entanto, só funciona quando há um dia de dois dígitos porque os dias numerados < 10 não têm um zero anterior.

Por exemplo, executo date e canalizo o resultado para awk . date outputs Sat Jan 1 04:56:10 GMT 2011 e, em seguida, o awk captura $2 e $3 e os alimenta no grep da seguinte forma

Jan 1

No entanto, quando há um dia de um único dígito, as mensagens em auth.log aparecem da seguinte forma

Jan  1 00:44:57 linux su[21249]: pam_unix(su:session): session closed for user root

Portanto, há dois espaços após Jan no auth.log , mas apenas um espaço após Jan no meu comando grep

Como posso modificar o comando para permitir o espaço adicional?

    
por conorgriffin 15.01.2011 / 06:02

1 resposta

7

Em vez de usar date | awk ... , você pode usar um especificador de formato com o comando date para o formato desejado. De acordo com a página date(1) man, %b é o nome abreviado do mês e %e é o dia do mês, espaço acolchoado, igual a %_d .

O comando date seguinte deve fornecer uma string no formato que você deseja:

date "+%b %e"

Você também pode colocar outros caracteres no especificador de formato, portanto, se você usar:

date "+^%b %e"

você obterá um padrão grep que corresponde à data apenas no início da linha. Isso evitaria correspondências falsas onde houvesse uma data na parte da mensagem do log.

Como apontado por Steven D, você também pode fazer isso com uma única invocação de grep :

auth()
{
    grep -E "$(date '+^%b %e')"'.*(BREAK-IN|Invalid|user|Failed|refused|su|Illegal)' /var/log/auth.log
}

Fiz algumas alterações com base nos problemas mencionados nos comentários relacionados à cotação. Minhas regras para citações são para usar aspas simples ao agrupar palavras separadas em uma única palavra e para proteger contra a expansão do shell de metacaracteres, e para usar aspas duplas somente quando você quiser expandir dentro de uma string multi-palavra.

A resposta original tinha a string de formato date entre aspas duplas, o que estava errado de acordo com as minhas regras acima. Eu agora mudei isso. Uma edição coloca a string do grep entre aspas duplas. Eu coloquei de volta entre aspas simples porque há, com muita freqüência, uma sobreposição entre metacaracteres de shell e metacaracteres de expressões regulares do grep (RE) que você quase sempre quer REs de aspas simples para grep. A string atual pode não precisar de aspas simples, mas se essa função do shell evoluir ao longo do tempo, ela poderá quebrar com alterações futuras.

Como a pergunta era sobre um comando para colocar dentro de um alias, havia um nível adicional de citações que não foi mostrado nesta resposta. Seria mais simples usar uma função de shell em vez de um alias, para que você não precise lidar com esse nível extra de citações. Citações aninhadas podem ficar confusas rapidamente, então qualquer coisa que você possa fazer para evitá-las, você deve fazer.

Eu testei isso como uma função de shell, usando a sugestão de Gilles para futzing a data e "funciona para mim".

    
por 15.01.2011 / 06:27