Ich habe einen Dateideskriptor mit erstellt
mkfifo fifo
Sobald etwas in diese Pipe geschrieben ist, möchte ich es sofort wiederverwenden . Sollte ich es benutzen
tail -f fifo
oder
while true; do cat fifo; done
?
Sie scheinen dasselbe zu tun und ich konnte keinen Leistungsunterschied messen. Wenn ein System jedoch nicht inotify unterstützt (z. B. Busybox), muss dies der Fall sein
tail -f -s 0 fifo
Dies verbraucht jedoch die CPU zu 100% (testen Sie es aus: mkfifo fifo && busybox tail -f -s 0 fifo & echo hi>fifo
/ Abbrechen mit fg 1
und CtrlC). Ist die while-true-cat die zuverlässigere Lösung?
tail -f
benötigen suchbare Eingaben. Das Verhalten vontail -f fifo
ist undefiniert. Wenntail -f -s 0 fifo
auf einigen Systemen funktioniert, verlassen sich diese Systeme auf nicht standardmäßiges Verhalten.tail
funktioniert gut auf fifos und ist erforderlich.-s
ist jedoch nicht Standard.tail
allein funktioniert gut,tail -f
benötigt aber suchbare Eingabe.tail -f fifo
soll noch nachgelesen werdenecho foo >fifo
.Antworten:
Wenn Sie das tun:
Angenommen, noch kein anderer Prozess hat das
fifo
zum Schreiben geöffnet ,cat
wird deropen()
Systemaufruf blockiert . Wenn ein anderer Prozess die Datei zum Schreiben öffnet, wird eine Pipe instanziiert undopen()
zurückgegeben.cat
ruftread()
eine Schleife auf undread()
blockiert, bis ein anderer Prozess Daten in die Pipe schreibt.cat
wird das Dateiende (eof) sehen, wenn alle anderen Schreibvorgänge ihren Dateideskriptor für das geschlossen habenfifo
. An welchen Stellencat
endet und das Rohr zerstört wird¹.Sie müssten
cat
erneut ausführen , um zu lesen, was danach in diefifo
(aber über eine andere Pipe-Instanz) geschrieben wird.Im:
Warten Sie
cat
,tail
bis ein Prozess eine Datei zum Schreiben geöffnet hat. Da Sie jedoch-n +1
von Anfang an kein zu kopierendestail
Element angegeben haben, müssen Sie bis eof warten, um herauszufinden, was die letzten 10 Zeilen waren, sodass Sie nichts sehen, bis das Schreibende geschlossen ist.Danach
tail
wird das fd nicht für die Pipe geschlossen, was bedeutet, dass die Pipe-Instanz nicht zerstört wird, und es wird weiterhin versucht, jede Sekunde aus der Pipe zu lesen (unter Linux kann das Abrufen durch die Verwendung voninotify
und einiger Versionen von vermieden werden GNUtail
macht das dort). Dasread()
wird wieder mit eof (sofort, weshalb Sie zu 100% CPU sehen mit-s 0
(die mit GNUtail
Mitteln nicht zwischen wartenread()
s statt für eine Sekunde des Wartens)) , bis ein anderen Prozess die Datei erneut zum Schreiben öffnet.Hier möchten Sie möglicherweise stattdessen verwenden
cat
, aber stellen Sie sicher, dass die Pipe-Instanz nach der Instanziierung immer verfügbar bleibt. Dafür können Sie auf den meisten Systemen Folgendes tun:cat
's stdin ist sowohl zum Lesen als auch zum Schreiben geöffnet, was bedeutet, dasscat
es niemals eof darauf sehen wird (es instanziiert auch die Pipe sofort, selbst wenn es keinen anderen Prozess gibt, der dasfifo
zum Schreiben öffnet ).Auf Systemen, auf denen dies nicht funktioniert, können Sie stattdessen Folgendes tun:
Auf diese Weise wird, sobald ein anderer Prozess das
fifo
Schreiben öffnet , der erste schreibgeschützte Vorgangopen()
zurückgegeben. An diesem Punkt führt die Shellopen()
vor dem Start den schreibgeschützten Vorgang auscat
, wodurch verhindert wird, dass die Pipe jemals wieder zerstört wird.Um es zusammenzufassen:
cat file
würde es nach der ersten Runde nicht aufhören.tail -n +1 -f file
: es würde nichtread()
jede sekunde nach der ersten runde nutzlos machen , es würde niemals eof auf der einen instanz der pipe geben, es würde nicht bis zu einer sekundenverzögerung geben, wenn ein zweiter prozess die rohre zum schreiben nach der runde öffnet zuerst hat man es geschlossen.tail -f file
. Darüber hinaus müsste es nicht warten, bis die erste Runde beendet ist, bevor etwas ausgegeben wird (nur die letzten 10 Zeilen).cat file
einer Schleife würde es nur eine Pipe-Instanz geben. Die in ¹ genannten Rennfenster würden vermieden.¹ An diesem Punkt, zwischen dem letzten
read()
, der eof anzeigt, und demcat
Beenden und Schließen des Leseendes der Pipe, gibt es tatsächlich ein kleines Fenster, in dem ein Prozess dasfifo
zum erneuten Schreiben öffnen könnte (und nicht blockiert werden kann, da es noch ein Leseende gibt ). Wenn es dann etwas schreibt, nachdem es beendetcat
wurde und bevor ein anderer Prozess dasfifo
zum Lesen öffnet , wird es mit einem SIGPIPE getötet.quelle
cat <>fifo
:cat will never see eof on it
. Ich verstehe, dass die Instanz offen bleibt. Aber wenn ein anderer Prozess einen EOF darauf schreibt, sollte er auch eintreffencat
, oder? Es wird also lieber ignoriert, da bidirektionale Rohrleitungen vorhanden sind. Vielen Dank!^D
Termios-Einstellung. Dies gilt jedoch nur für E / A-Vorgänge an Endgeräten, dh an Geräte mit seriellen / Pty-Zeichen, denen eine Tty-Line-Disziplin zugeordnet ist (und dies nur in bestimmten Betriebsarten), keine Pipes, keine Socket-Paare, keine regulären Dateien, keine Verzeichnisse , keine Geräte blockieren, keine anderen Zeichengeräte.Lassen Sie mich eine andere Lösung vorschlagen. Pipe steht zum Lesen zur Verfügung, solange ein Prozess am zweiten Ende schreibt. So können Sie
cat
im Hintergrund (oder in einem anderen Terminal) eine Fälschung erstellen , zum Beispiel:Jetzt können Sie so lange an fifo schreiben, wie Sie möchten, und wenn Sie fertig sind, töten Sie einfach den Strom
cat
mit C-cundfg
bringen Sie ihn dann zuerstcat
aus dem Hintergrund und schließlich C-d, um ihn zu stoppen.quelle
/dev/null
,cat
wird sein Standardwert so, dass er unmittelbar nach dem Start beendet wird. In Shells, die dies nicht tun und / oder von einer interaktiven Shell in einem Terminal ausgeführt werden,cat
wird sie wahrscheinlich angehalten, wenn versucht wird, vom Terminal zu lesen, ohne im Vordergrund zu stehen.