So erstellen Sie eine Cat-Named-Pipe ohne Wartezeit

So erstellen Sie eine Cat-Named-Pipe ohne Wartezeit

Wenn sich in einer benannten Pipe nichts befindet und ich Folgendes tue:

cat my_named_pipe

es wird gewartet, bis Daten eintreffen. Gibt es ein Flag, mit dem ich sofort beenden kann, wenn keine Daten zum Lesen vorhanden sind? Oder vielleicht einen anderen Befehl als cat, den ich verwenden kann?

Ich habe auch versucht:

read val < "$my_named_pipe";

aber dies wartet auch auf den nächsten Datenblock – ich möchte nicht warten, wenn der FIFO leer ist.

Antwort1

Um ein Hängenbleiben bei Abwesenheit eines Writers zu verhindern cat(in diesem Fall hängt das Öffnen des FIFO und nicht das Lesen daraus), können Sie Folgendes tun:

cat 0<> "$my_named_pipe" <"$my_named_pipe"

Die erste Umleitung öffnet im Lese- und Schreibmodus, was auf den meisten Systemen nicht blockiert und die Pipe instanziiert, auch wenn es weder einen Schreiber noch einen Leser gibt. Dann würde das zweite Öffnen (diesmal schreibgeschützt) nicht blockieren, da es jetzt mindestens einen Schreiber (sich selbst) gibt.

Dies 0ist nur in neueren Versionen von ksh93 erforderlich, in denen der Standard-FD <>von 0 auf 1 geändert wurde.

Außerdem ksh93würde das in nicht funktionieren, wenn catdie Shell eingebaut ist, wie wenn ksh93aufgerufen wird, wenn /opt/ast/binvor /binin $PATHoder nach einem Aufruf von steht , builtin catwie beim <"$my_named_pipe", (nehme ich an) speichert ksh93 das vorherige Ziel von stdin in einem separaten Dateideskriptor, der die Pipe offen halten würde. Sie können das umgehen, indem Sie stattdessen Folgendes schreiben:

cat 3<> "$my_named_pipe" <"$my_named_pipe" 3<&-

(wodurch Ihrer Meinung nach auch die Absicht klarer zum Ausdruck kommt)

Beachten Sie, dass dadurch <>auf der Pipe auch andere Leser für das FIFO freigeschaltet werden.

Wenn es einige Schreiber gäbe, catmüssten diese trotzdem deren gesamte Ausgabe lesen und warten, bis sie ihr Ende der Pipe geschlossen haben. Sie könnten die Pipe im nicht blockierenden Modus öffnen, wie bei GNU dd:

dd bs=64k if="$my_named_pipe" iflag=nonblock status=noxfer

Das liest nur aus der Pipe, solange Daten darin sind, und beendet mit einem

dd: error reading 'fifo': Resource temporarily unavailable

Fehler, wenn es keine mehr gibt, und andere Leser nicht freischalten, aber das bedeutet, dass Sie einige der Ausgaben der Writer verpassen könnten, wenn diese langsamer in die Pipe schreiben als Sie ( dd) beim Lesen.

Ein anderer Ansatz könnte darin bestehen, ein Timeout einzurichten, wenn über einen längeren Zeitraum keine Eingabe erfolgt ist. Dies kann beispielsweise durch die Verwendung socatder -TOption erfolgen:

socat -u -T1 - - 0<> "$my_named_pipe" <"$my_named_pipe"

Dies würde beendet, wenn innerhalb einer Sekunde nichts aus der Leitung gekommen wäre.

Antwort2

Etwas ganz Einfaches wäre, catsofort nach dem Lesen des FIFOs zu beenden, unabhängig davon, ob Daten vorhanden sind oder nicht. Dies könnte man mit tun timeout, und zwar wie folgt:

timeout 2 cat my_named_pipe

Oben timeoutwird zwei Sekunden gewartet, bevor die Beendigung von cat erzwungen wird. Wenn beim Ausführen etwas in der benannten Pipe gepuffert ist cat, wird es auf stdout gedruckt.

Vielleicht nicht die sauberste Lösung, aber sie erfüllt ihren Zweck.

Ich hoffe es hilft.

verwandte Informationen