Redirecionando a saída dependendo do grep regex

8

Estou usando gradle run para iniciar um servidor REST. A saída do servidor REST é semelhante a esta:

XXX.XXX.XX.XXX - <moreinfo>
randomtext
randomtext
XXX.XXX.XX.XXX - <moreinfo>
XXX.XXX.XX.XXX - <moreinfo>
randomtext
XXX.XXX.XX.XXX - <moreinfo>

XXX.XXX.XX.XXX aqui é um endereço IP, o texto aleatório é uma mensagem de erro. Toda saída é direcionada para stdout, infelizmente.

Como posso direcionar todas as linhas que começam com um endereço IP para um arquivo chamado err.log e todas as outras linhas para all.log ?

Infelizmente, gradle run só pode ser iniciado uma vez e não é interrompido, pois é um servidor REST.

Talvez use uma combinação tee , grep ?

    
por polym 06.07.2014 / 23:55

2 respostas

8

No Bash, você pode usar substituição de processos com tee:

tee >(grep XXX > err.log) | grep -v XXX > all.log

Isso colocará todas as linhas correspondentes a XXX em err.log e todas as linhas em all.log . >( ... ) cria o processo entre parênteses e conecta sua saída padrão a um pipe. Isso funciona em zsh e em outros shells modernos também.

Você também pode usar o comando pee de moreutils :

pee "grep XXX > err.log" "grep -v XXX > all.log"

pee redireciona a entrada padrão para vários comandos ("tee para pipes").

Outra alternativa é com o awk:

awk '{ if (/^([0-9]{1,3}\.){3}[0-9]{1,3}/) { print > "err.log" } else { print > "all.log" } }'

Isso testa todas as linhas em relação à expressão e grava tudo em err.log se corresponder e all.log se não corresponder.

A expressão regular awk também é adequada para grep -E (embora corresponda alguns endereços incorretos - 999.0.0.0 e assim por diante - mas isso provavelmente não é um problema).

    
por 07.07.2014 / 00:11
4

Assim, parece que gradle run não está em conformidade com tee , pee , grep e redirecionamento de io. Ele sempre pára de ler após 4096 bytes.

Para contornar esse problema, eu read de cada linha de gradle run . Eu não testei ainda, mas acho que ler uma linha com mais de 4k caracteres também falhará.

De qualquer forma, aqui está o código para resolver minha pergunta especificamente:

#!/bin/bash
STDOUTLOG="/log/stdout.txt"
STDERRLOG="/log/stderr.txt"
while read -r line; do
    [[ $line =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}.* ]] && printf '%s\n' "$line" >> "$STDERRLOG" && continue
    printf '%s\n' "$line" >> "$STDOUTLOG"
done < <(gradle run)
    
por 07.07.2014 / 03:30