Ich möchte Änderungen an einer Datei über verfolgen tail -f
und dann die erste Zeile ausdrucken, die einem grep
Befehl entspricht, bevor ich sie beende. Was ist der einfachste Weg, dies zu tun? Bisher habe ich mit Dingen experimentiert wie:
tail -f foo.log | grep 'bar' | head -1
Die Pipeline hängt jedoch nur, vermutlich aufgrund von Pufferung. Ich habe es auch versucht
tail -f foo.log | grep --line-buffered 'bar' | head -1
Dadurch wird die Zeile ausgedruckt, aber der Vorgang wird erst beendet, wenn ich ^ C drücke, vermutlich weil zum Beenden eine zweite Eingabezeile erforderlich ist head -1
. Was ist der beste Weg, um dieses Problem zu lösen?
perl -e '$|++; my $i = "a"; while (1) { print $i, "\n"; $i++; select undef, undef, undef, 0.1}' | grep -m 1 aa
- Alle 0,1 Sekunden wird die nächste Zeichenfolge gedruckt, zuerst "a", dann "b", ... "z", "aa", "ab" ... - grep wird nach "aa" beendet, also ist es so sollte ~ 2,7 Sekunden nach dem Start sein. und es funktioniert. Das Problem könnte sein, wenn Sie etwas anderes zwischen tail -f .. und | haben grep - wie ein anderer grep, sed oder so ähnlich.Das Konstrukt <() funktioniert nur in Bash. Meine Lösung ist:
Neben der Arbeit in einer POSIX-Shell besteht ein weiterer Vorteil darin, dass die Wartezeit mit einem Timeout-Wert begrenzt werden kann. Beachten Sie, dass der Ergebniscode dieses Scriptlets umgekehrt ist: 0 bedeutet, dass das Zeitlimit erreicht wurde.
quelle
tail -f
WartenSIGPIPE
, das, wie bereits von depesz ausgeführt, ersttail -f
nach einem erfolgreichengrep -m 1
Match durch ein erneutes Schreiben in eine geschlossene Pipe ausgelöst werden kann, kann vermieden werden, wenn dertail -f
Befehl in den Hintergrund gestellt und seine Hintergrund-grep
PID an die Subshell gesendet wird, was wiederum der Fall ist implementiert einentrap
On-Exit, dertail -f
explizit beendet wird.quelle
Aufbauend auf der Antwort https://superuser.com/a/275962/37154 wurde mir klar, dass, wenn die
tail
zu spät starten würde, möglicherweise bereits eine Instanz der angegebenen Zeichenfolge verstrichen ist. Die Lösung besteht darin, die gesamte Datei mit einer Endliste zu versehen.quelle
Ich denke, dass das Anwenden von Unpuffer so,
würde funktionieren. Ich bin jedoch nicht in einem System, in dem ich es testen kann, und ich kann nicht rechtfertigen, warum es funktionieren würde, während
grep --line-buffered
dies nicht der Fall ist. Ich habe jedoch diese Alternative ausprobiert, die zu funktionieren scheint:Wenn die Übereinstimmung mit
bar
gefunden wurde, wird siep
gedruckt undq
sofort beendet.quelle