Reindirizzamento dell'output in base al regex di grep


8

Sto usando gradle runper avviare un server REST. L'output del server REST è simile al seguente:

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.XXXqui c'è un indirizzo IP, i testi casuali sono messaggi di errore. Tutto l'output è diretto allo stdout, purtroppo.

Come posso indirizzare tutte le linee che iniziano con un indirizzo IP verso un file chiamato err.loge ogni altra linea verso all.log?

Sfortunatamente, gradle runpuò essere avviato solo una volta e non si arresta, poiché è un server REST.

Forse utilizzare una tee, grepcombinazione?

Risposte:


8

In Bash, è possibile utilizzare la sostituzione del processo con tee:

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

Ciò inserirà tutte le righe corrispondenti a XXX in err.loge tutte le righe in all.log. >( ... )crea il processo tra parentesi e collega l'output standard a una pipe. Funziona anche in zsh e in altre shell moderne.

Puoi anche usare il peecomando da moreutils :

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

pee reindirizza l'input standard a più comandi ("tee for pipe").

Un'ulteriore alternativa è con awk:

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

Questo mette alla prova ogni riga rispetto all'espressione e scrive tutto err.logse corrisponde e all.logse non lo fa.

L'espressione regolare awk è adatta grep -Eanche per (sebbene corrisponda ad alcuni indirizzi errati - 999.0.0.0e così via - ma probabilmente non è un problema).


Hmm err.logè vuoto e tutto l'output viene reindirizzato all.logutilizzando il teecomando sopra.
polimero

Verifica che la tua espressione regolare corrisponda effettivamente alle linee giuste - se err.logesiste affatto, il comando è stato eseguito ma non è emerso nulla. grep -Econ l'espressione usata nel comando awk dovrebbe corrispondere, o lo fa qui.
Michael Homer,

Ah ok ho capito. Puoi modificare la tua domanda in modo che all.lognon contenga le linee corrispondenti nell'espressione grep?
polimero

Fatto - non ero sicuro di quale volevi, quindi avevo entrambi.
Michael Homer,

Oh maledizione, ha funzionato. Ho sovrascritto all.loge err.logcon un vecchio comando. Dispiace per la confusione. Grazie, sei fantastico :)) !!
polimero

4

Così, sembra che gradle runnon rispetti tee, pee, grepe io-reindirizzamento. Smette sempre di leggere dopo 4096 byte.

Per aggirare questo problema, ho readogni riga di gradle run. Non l'ho ancora testato, ma immagino che anche la lettura di una riga di oltre 4k caratteri fallirà.

Comunque, ecco il codice per risolvere in modo specifico la mia domanda:

#!/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)

1
Dovresti usare read -r linee printf '%s\n' "$line"per evitare che alcuni casi limite rompano le cose.
nyuszika7h

@nyuszika7h Grazie! Ho modificato la risposta di conseguenza :).
polimero
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.