Piping Schwanz -f in awk


9

Ich versuche, tail -f in awk zu leiten, um eine Protokolldatei in Echtzeit zu überwachen, aber Beispielen zufolge sollte es kein Problem geben, aber ich kann es nicht zum Laufen bringen.

Hier ist der Befehl, den ich ausführe

tail -f logfile.log | awk -F" " '{print $1, $2, $7, $8}'

Wenn ich meine Datei jedoch mit nano edit a line bearbeite, wird sie nicht in Echtzeit gedruckt. Wenn ich den Befehl awk direkt ausführe, wird meine neue Zeile im Ergebnis angezeigt.


Antworten:


12

Sie sehen es nicht in Echtzeit, da Rohre aus Effizienzgründen gepuffert werden. tail -fmuss den Puffer füllen, typischerweise 4 kB, bevor die Ausgabe an übergeben wird awk.

Ein Fix besteht darin, den Unbuffer-Befehl zu verwenden, der Teil des Expect-Pakets ist:

unbuffer tail -f logfile.log | awk -F" " '{print $1, $2, $7, $8}'

Dies führt tailzu dem Gedanken, dass es in ein interaktives Terminal schreibt. Infolgedessen puffert es nicht.

Weitere Informationen finden Sie unter /unix/25372/turn-off-buffering-in-pipe

Wenn Sie über GNU coreutils 7.5 oder besser verfügen, können Sie alternativ die Ausgabepufferung mit dem Befehl stdbuf deaktivieren:

stdbuf -o0 tail -f logfile.log | awk -F" " '{print $1, $2, $7, $8}'

Leider scheint die stdbuf-Lösung auch nicht zu funktionieren.
Gimpycpu

Aber Sie haben Recht, wenn ich ~ 10 Zeilen hinzufüge, wird der Puffer geleert. Während der Code funktioniert, funktioniert der ungepufferte Teil nicht
gimpycpu

Ich habe gerade einen Tippfehler im Befehl stdbuf behoben. Abgesehen davon kann es ein zusätzliches Problem geben, bei dem Ihr Editor die Datei nicht auf eine Weise aktualisiert, die ausgelöst wird tail. Können Sie versuchen, ohne den Editor nur an die Datei anzuhängen? Führen Sie beispielsweise date >>logfile.logeinige Male in einem Fenster aus und prüfen Sie, ob awkdie Aktualisierungen in einem anderen Fenster gedruckt werden.
John1024

Ja, ich habe versucht, das Echo "Meine lange Zeichenfolge hier" >> logfile.log aus einem anderen Kittfenster anzuzeigen. Wenn ich diese Zeile ungefähr 10 Mal ausführe, wird der Befehl awk ausgeführt.
Gimpycpu

@gimpycpu Mit habe nanoich verschiedene Ergebnisse erhalten, je nachdem, wie ich die Datei vor dem Speichern bearbeitet habe. Die Verwendung echo "My long string here" >> logfile.logfunktioniert jedoch jedes Mal bei mir.
John1024

6

Ich denke, die Antwort von @ John1024 ist nicht ganz richtig, da das stdbuf -o0Präfix falsch platziert ist. Es gehört als Präfix zum awkBefehl, nicht zum tail -fBefehl, daher sollte der richtige Befehl lauten:

tail -f logfile.log | stdbuf -o0 awk -F" " '{print $1, $2, $7, $8}'

Beachten Sie auch, dass nicht alle Versionen von awk in dieser bestimmten Konfiguration funktionieren. IOW, wenn Sie diese bestimmte Befehlszeichenfolge benötigen, um wie geschrieben zu funktionieren, probieren Sie verschiedene awk / gawk / mawk-Versionen aus, bis Sie eine finden, die funktioniert.


Ich habe den Kommentar-Link verwendet, um dies zu tun, aber es hat mich aufgrund des unzureichenden Rufs verhindert. Welche Mittel hätte ich verwenden sollen?
kenneth558

Schlagen Sie die Änderung des Beitrags vor, zu dem Sie den Vorschlag hatten ( Option "Diese Antwort verbessern" ). Das können auch anonyme Benutzer.
Kenorb

2

Sie können die Pufferung aufheben, indem Sie eine while-Schleife hinzufügen, wie im folgenden Beispiel angegeben. Ich habe dies an einer laufenden Protokolldatei getestet und es hat bei mir funktioniert.

tail -f input.log | while read a; do echo "$a" | awk -F" " '{print $1, $2, $7, $8}' >> output.log; done

Sie möchten generell vermeiden, in Rohrleitungen zu führen, while readwenn Sie können. Wenn Sie nicht können, würde das Platzieren des awkRohrs nach dem donedie Leistung etwas verbessern. Die richtige Lösung besteht jedoch darin, die Pufferung zu deaktivieren und nicht zu umgehen.
Tripleee

Dies half mir, Protokollnachrichten auf einem eingebetteten System unbufferstdbuf
anzuzeigen

Dadurch wird für awkjede Zeile ein neuer Prozess erstellt, anstatt ihn einmal auszuführen.
Victor Sergienko

0

Weder stdbuf noch unbuffer scheinen für mich zu funktionieren (Ubuntu 18.04), aber die Verwendung einer Named Pipe funktioniert. Ich habe ein Shell-Skript erstellt, das Folgendes enthält:

mkfifo /tmp/pipe
awk -F" " '{print $1, $2, $7, $8}' < /tmp/pipe &
tail -f input.log > /tmp/pipe
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.