Warum erzeugt der folgende Befehl keine Ausgabe?
$ tail -f /etc/passwd | tail
Nachdem ich über das Puffern gelesen hatte , versuchte ich Folgendes ohne Erfolg:
$ tail -f /etc/passwd | stdbuf -oL tail
Beachten Sie, dass Folgendes zu einer Ausgabe führt:
$ tail /etc/passwd | tail
So funktioniert das:
$ tail -f /etc/passwd | head
Ich benutze Tail Version 8.21 (GNU Coreutils).
Antworten:
Ich dachte, ich hätte alles in UNIX gesehen. Diese Frage hat mich aus meiner Selbstgefälligkeit gerissen. Was für eine tolle Frage!
tail
zeigt die letzten X Zeilen.tail -f
funktioniert genauso, aber im Wesentlichen in einer Endlosschleife: Zeigen Sie beim Start die letzten X Zeilen der Datei an, und verwenden Sie dann etwas Magie des Betriebssystems (wie inotify), überwachen Sie und zeigen Sie neue Zeilen an.Um seine Arbeit zu erledigen,
tail
muss es möglich sein, das Ende der Datei zu lokalisieren. Wenntail
das Dateiende nicht gefunden wird, werden die letzten X-Zeilen nicht angezeigt, da "last" undefiniert ist. Was machttail
man in diesem Fall? Es wartet, bis es das Ende der Datei findet.Bedenken Sie:
Dies scheint niemals Fortschritte zu machen, da es nie ein definitives Dateiende gibt
chatter
.Sie erhalten das gleiche Verhalten, wenn Sie
tail
nach den letzten Zeilen einer Dateisystem-Pipe fragen . Erwägen:stdbuf
Das wahrgenommene Problem zu umgehen war ein nobler Versuch. Die wichtigste Tatsache ist jedoch, dass die E / A-Pufferung nicht die Hauptursache ist: Das Fehlen eines bestimmten Dateiendes ist die Ursache. Wenn Sie den Quellcode von tail.c auschecken , wird derfile_lines
Funktionskommentar wie folgt angezeigt :und das ist die Magie. Sie benötigen ein Dateiende, damit tail in jeder Konfiguration funktioniert.
head
hat diese Einschränkung nicht, es braucht nur einen Dateianfang (was es vielleicht nicht hat, versuchen Sie eshead test.pipe
). Stream-orientierte Tools mögensed
undawk
brauchen weder einen Anfang noch ein Ende der Datei: Sie arbeiten mit Puffern.quelle
tail -f
's Schwanz ist eigentlich etwas Unbekanntes in der Gegenwart, also woher soll der nächste estail
wissen. Auf der anderen Seite isttail -f
der Kopf schon bekannt und könnte daher verarbeitet werden.Oder einfacher ausgedrückt:
tail
Ist relativ zum Ende der Datei, aber der Ausgabestreamtail -f
hat keine EOF erhalten (zumindest nicht vor dessen Beendigung).Wenn Sie die erste finden
tail
‚s pid und töten sie, sollten Sie dann die Ausgabe von dem zweiten sehen.quelle
Technische Antwort
Wenn ein Stream als Eingabe ausgeführt wird, wird
tail
einn
-zeiliger Puffer beibehalten, der beim Lesen des Streams gefüllt wird. Diese Zeilen können jedoch erst ausgegeben werden, wenn das Ende des Streams erreicht ist, dh,EOF
wenn versucht wird, von der Eingabe zu lesen, wird ein spezieller Code empfangen Strom. Der Aufruftail -f
wird nicht beendet, daher wird er seinen Stream niemals schließen, was es unmöglich macht, z. B. die 10 letzten Zeilen dieses Streams zurückzugeben.quelle
Die Funktion von
tail
ist, den letzten Teil - "Schwanz" - der Eingabe oder Datei anzuzeigen. (Die Option-f
handelt davon, was später getan wird, sodass dies hier nicht relevant ist.)Denken wir über eine Datei nach:
Was ist der letzte Teil einer Datei ?
Angenommen, es sind die letzten n Zeilen einer Datei.
Wenn wir die Zeile
i
der Eingabedatei lesen , wie sollen wir entscheiden, ob sie gedruckt werden soll oder nicht?Wir wissen nicht, ob es im letzten Teil ist - weil wir nicht wissen, welche die letzte Zeile sein wird. Also können wir es jetzt nicht drucken.
Wir müssen die Linie so lange beibehalten, bis klar wird, dass sie Teil der letzten
n
Linien ist oder nicht mehr dazu gehören kann, weil wirn
weitere Linien kennenWenn wir jetzt zum Ende der Datei kommen , wissen wir, dass die letzten
n
Zeilen, die wir behalten haben, tatsächlich die letztenn
Zeilen der Datei sind.Nun im Fall von
Der erste
tail
liest die Datei und wartet dann, bis er weitere Daten daraus abruft, um diese auch auszuschreiben. Daher wird dem zweiten Ende kein Dateiende signalisiert, wenn das Ende der gelesenen Datei erreicht ist. Andernfalls wird der zweitetail
Benutzer nie über das Ende der Datei informiert , sodass er nie herausfinden kann, welche der letzten Zeilen gedruckt werden sollen.quelle