Nicht blockierende gepufferte Named Pipe?

20

Ich suche nach etwas, von dem ich vermute, dass es es nicht gibt: Eine nicht blockierende gepufferte Named Pipe (FIFO) zur Verwendung über die Befehlszeile. Gibt es so etwas?

Hier ist der Anwendungsfall: Angenommen, ich habe einen Prozess, der eine lange Zeit im Hintergrund abläuft und eine Menge Ausgabe anstößt stdout. Ich kümmere mich nicht wirklich um die Ausgabe und möchte sie nicht speichern (vielleicht habe ich nicht genug Platz dafür), aber ich möchte in regelmäßigen Abständen "vorbeischauen" und verfolgen, was es tut, und dann wieder aussteigen und überlasse es seiner Arbeit. Daher möchte ich die Ausgabe auf diese theoretisch gepufferte, nicht blockierende Named Pipe umleiten und dann regelmäßig darauf zugreifen.

Im Grunde möchte ich so anfangen ( 10Mals Größe des Puffers):

mkmagicfifo magicfifo 10M
spewingprocess > magicfifo &

... und schauen Sie regelmäßig vorbei, um zu sehen, was los ist ...

tail -f magicfifo

... ohne die magicfifo gesamte Ausgabe zu speichern (also keine normale Datei) und ohne den Ausspeisungsprozess zu blockieren, wenn sie voll ist und nicht abgegriffen wird (also keine ganz normale Named Pipe).

Ich denke nicht, dass Lösungen dies beinhalten tailoder prunetun werden (naja, ich kann mir eine Problemumgehung vorstellen, die dies beinhaltet tail), da tailich trotzdem alle Daten irgendwo speichern müsste (wenn ich sie sehen und nicht mehr sehen möchte). und prunemuss die Datei neu schreiben, vermutlich (ich gebe zu, ich habe das nicht versucht / bewiesen), um die Umleitung des Prozesses zu unterbrechen, der die gesamte Ausgabe generiert.

Ich erwarte, ich könnte ein Hilfsprogramm schreiben, um dies zu tun, aber * nix hat so viele coole Aspekte von Dateien und Pipes und so, dass ich einfach nicht anders kann, als zu glauben, dass es das gibt, und ich weiß es einfach nicht.

Also: Gibt es so etwas und wenn ja, was ist es?

TJ Crowder
quelle
1
Was Sie beschreiben, ist ein "Ringpuffer" oder "Ringpuffer". Ich kenne keine Kommandozeilen-Tools, um so etwas zu pflegen, obwohl es trivial wäre, sie zu erstellen.
Shawn J. Goff
2
Schauen Sie sich die Lösungen an, die unter "Linux non-blocking fifo (On-Demand-Protokollierung)", stackoverflow.com/questions/7360473/… beschrieben sind .
1
Es sieht so aus, als ob dies auf StackOverflow
James Blackburn
@ JamesBlackburn: Danke! Sehr interessant.
TJ Crowder

Antworten:

16

Ich denke, was Sie suchen, ist GNU screen. Es verwaltet einen Puffer, um den letzten Bildschirm oder zwei Ausgaben von einem oder mehreren Programmen zu speichern, und ermöglicht es Ihnen, die Verbindung zu trennen und später zurückzukehren.

Psusi
quelle
+1 für Bildschirmvorschläge. Übrigens können Sie es so konfigurieren, dass es viele "Verlaufslinien" enthält.
Herr Shunz
1
Vielen Dank. Können Sie ein Beispiel geben, wie Sie das auf die Befehle anwenden würden, die ich in meiner Frage gezeigt habe? Auf der Manpage steht, dass es sich um einen Fenstermanager handelt (ich denke, sie bedeuten im Endeffekt nichts Grafisches, aber dennoch). Und könnte ich trotzdem (über ssh) ein- und aussteigen, wenn nötig? (ZB Ops auf Remote-Servern.)
TJ Crowder
Ja, Sie können den GNU-Bildschirm auf diese Weise verwenden. Sie würden eine neue (möglicherweise benannte) Sitzung erstellen, Ihren Befehl in dieser Sitzung ausführen und dann die Verbindung trennen.
TML
2
Es gibt auch tmuxund dtach- alles in der gleichen Klasse von Terminal-Multiplexer / Session-Manager-Anwendungen sollte in der Lage sein, dasselbe zu erreichen.
JW013
5

Sie können verwenden pv, es bietet so viel Pufferung, wie Sie in einer Pipeline möchten. Du kannst es so benutzen:

sprewingprocess | pv -B 1g > ordinaryfifo &

Das würde Ihnen bis zu 1 GB Pufferung zwischen spewingprocessund dem FIFO geben. Die meisten Linux-Distributionen bieten pvein Paket mit dem Namen, ob Sie es glauben oder nicht, an pv.

David Schwartz
quelle
Danke, aber wäre dieser Block nicht einmal voll, wenn ich die Ziel-Named-Pipe nicht gelesen hätte?
TJ Crowder
1
Ja, aber welche Wahl haben Sie? In einem endlichen Universum können Sie nicht buchstäblich unbegrenzt puffern.
David Schwartz
Die andere Wahl ist, wie ich in meiner Frage beschrieben habe: Nicht alle Ausgaben speichern. Wenn der Puffer voll ist, wird das älteste Zeug weggeworfen.
TJ Crowder
Hmm, ich habe das getestet und es funktioniert leider nicht ganz. Wenn der Prozess, der das FIFO liest, für eine Weile aufhört zu lesen, blockiert pv den Versuch, in das FIFO zu schreiben, und blockiert das Lesen von Daten in den Pufferspeicher von pv, weil es nicht multithreaded ist. Der pv-Puffer füllt sich also nur weiter, während der Prozess, der das FIFO liest, weiter liest. pv kann zwar einige Daten lesen und puffern, hindert den Schreiber jedoch nicht daran, sie vollständig zu blockieren.
Daniel S. Sterling
1

Ich hatte das gleiche problem Dies ist meine erste Lösung. Schreiben Sie zuerst die Ausgabe in eine Datei, die nach jeder Zeile abgeschnitten wird, damit sie nicht unendlich groß wird:

spewingprocess | while read line; do echo $line > buffer.txt ; done

Lesen Sie dann mit tail aus der Datei (wobei 2> /dev/nulldie Fehlermeldung "Datei abgeschnitten" beseitigt wird):

tail -f ./buffer.txt 2> /dev/null

Auf diese Weise wächst der Puffer nicht und wir können multiplexen, z. B. so viele Tails ausführen, wie wir möchten. Das Problem bei diesem Ansatz ist jedoch, dass wir Daten verlieren können, wenn wir schneller abschneiden, als der Schwanz lesen kann, wie dieser Test zeigt:

for ((i=0; ; i++)) ; do echo "$i" ; done | while read line; do  echo $line > buffer.txt ; done
tail -f ./buffer.txt 2> /dev/null > log.txt

Nach einiger Zeit sind die erste und letzte Zeile:

$ head -n 1 log.txt
0
$ tail -n 1 log.txt
78783

Da die Datei jedoch weniger Zeilen enthält, gehen einige verloren:

$ wc log.txt
67087  67087 392819 log.txt

Dies scheint dennoch eine gute Lösung zu sein, wenn Sie sich nicht so sehr für Datenverluste interessieren oder wenn Ihr Spewing-Prozess nicht schnell genug ist, um Datenverluste zu verursachen.

bterwijn
quelle