Umleiten der Ausgabe abhängig von Grep Regex

8

Ich verwende gradle run, um einen REST-Server zu starten. Die Ausgabe des REST-Servers sieht folgendermaßen aus:

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.XXXHier ist eine IP-Adresse, zufälliger Text sind Fehlermeldungen. Alle Ausgaben sind leider an stdout gerichtet.

Wie kann ich alle Zeilen, die mit einer IP-Adresse beginnen, an eine aufgerufene Datei err.logund jede andere Zeile an leiten all.log?

gradle runKann leider nur einmal gestartet werden und hört nicht auf, da es sich um einen REST-Server handelt.

Vielleicht eine verwenden tee, grepKombination?

polym
quelle

Antworten:

8

In Bash können Sie die Prozessersetzung durch tee verwenden:

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

Dadurch werden alle Zeilen, die mit XXX übereinstimmen err.log, und alle Zeilen in eingefügt all.log. >( ... )Erstellt den Prozess in Klammern und verbindet seine Standardausgabe mit einer Pipe. Dies funktioniert auch in zsh und anderen modernen Shells.

Sie können auch den peeBefehl von moreutils verwenden :

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

pee Leitet die Standardeingabe auf mehrere Befehle um ("Tee for Pipes").

Eine weitere Alternative ist mit awk:

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

Das testet einfach jede Zeile gegen den Ausdruck und schreibt das Ganze hinein, err.logob es übereinstimmt und all.logob es nicht übereinstimmt .

Der reguläre Ausdruck awk ist auch für geeignet grep -E(obwohl er mit einigen schlechten Adressen übereinstimmt - 999.0.0.0und so weiter -, aber das ist wahrscheinlich kein Problem).

Michael Homer
quelle
Hmm err.logist leer und alle Ausgaben werden all.logmit dem teeobigen Befehl umgeleitet .
Polym
Überprüfen Sie, ob Ihr regulärer Ausdruck tatsächlich mit den richtigen Zeilen übereinstimmt. Wenn überhaupt err.logvorhanden, wurde der Befehl ausgeführt, aber es wurde nichts ausgegeben. grep -Emit dem Ausdruck, der im Befehl awk verwendet wird, sollte übereinstimmen, oder hier.
Michael Homer
Ah ok ich habe es verstanden. Können Sie Ihre Frage so ändern, dass all.logsie keine übereinstimmenden Zeilen im grep-Ausdruck enthält?
Polym
Fertig - war mir nicht sicher, welches du wolltest, also hatte ich beides.
Michael Homer
Oh verdammt leid, es hat funktioniert. Ich habe überschrieben all.logund err.logmit einem alten Befehl. Entschuldigung für die Verwirrung. Danke, du bist großartig :)) !!
Polym
4

So sieht es aus wie gradle runnicht mit nicht entspricht tee, pee, grepund io-Umleitung. Nach 4096 Bytes hört es immer auf zu lesen.

Um dieses Problem zu umgehen, habe ich readjede Zeile von gradle run. Ich habe es noch nicht getestet, aber ich denke, dass das Lesen einer Zeile mit mehr als 4.000 Zeichen ebenfalls fehlschlagen wird.

Wie auch immer, hier ist der Code, um meine Frage speziell zu lösen:

#!/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)
polym
quelle
1
Sie sollten verwenden read -r lineund printf '%s\n' "$line"einige zu vermeiden Rand Fällen brechen Dinge.
Nyuszika7h
@ nyuszika7h Danke! Ich habe die Antwort entsprechend geändert :).
Polym