Automatische EOFs an eine Named Pipe verhindern und ein EOF senden, wenn ich es möchte

Automatische EOFs an eine Named Pipe verhindern und ein EOF senden, wenn ich es möchte

Ich habe ein Programm, das automatisch beendet wird, wenn ein EOF in einem bestimmten Stream gelesen wird (im folgenden Fall stdin).
Jetzt möchte ich ein Shell-Skript erstellen, das eine benannte Pipe erstellt und die stdin des Programms damit verbindet. Dann schreibt das Skript in die PipemehrmalsVerwendung von echound cat(und anderen Tools, die beim Beenden automatisch ein EOF generieren). Das Problem, mit dem ich konfrontiert bin, ist, dass, wenn das erste echoerledigt ist, ein EOF an die Pipe gesendet wird und das Programm beendet wird. Wenn ich etwas wie tail -fdann verwende, kann ich kein EOF senden, wenn ich das Programm beenden möchte. Ich suche nach einer ausgewogenen Lösung, aber ohne Erfolg.
Ich habe bereits herausgefunden, wie man EOFs verhindert und wie man manuell ein EOF sendet, aber ich kann sie nicht kombinieren. Gibt es einen Hinweis?

#!/bin/sh
mkfifo P
program < P & : # Run in background
# < P tail -n +1 -f | program
echo some stuff > P # Prevent EOF?
cat more_stuff.txt > P # Prevent EOF?
send_eof > P # How can I do this?
# fg

Antwort1

Wie andere bereits erwähnt haben, erhält der Leser einer Pipe EOF, sobald keine Schreiber mehr übrig sind. Die Lösung besteht also darin, sicherzustellen, dass es immer einen Schreiber gibt, der die Pipe offen hält. Dieser Schreiber muss nichts senden, sondern sie nur offen halten.

Da Sie ein Shell-Skript verwenden, besteht die einfachste Lösung darin, der Shell mitzuteilen, dass sie die Pipe zum Schreiben öffnen und sie dann wieder schließen soll, wenn Sie fertig sind.

#!/bin/sh
mkfifo P
exec 3>P # open file descriptor 3 writing to the pipe
program < P
# < P tail -n +1 -f | program
echo some stuff > P
cat more_stuff.txt > P
exec 3>&- # close file descriptor 3

Beachten Sie, dass, wenn Sie die letzte Zeile weglassen, Dateideskriptor 3 automatisch geschlossen wird (und der Leser somit EOF erhält), wenn das Skript beendet wird. Abgesehen von der Bequemlichkeit bietet dies auch eine Art Sicherheit, falls das Skript aus irgendeinem Grund vorzeitig beendet werden sollte.

Antwort2

Eine Pipe empfängt EOF, wenn der letzte Writer weggeht. Um dies zu vermeiden, stellen Sie sicher, dass immer ein Writer vorhanden ist (ein Prozess, der die Pipe zum Schreiben geöffnet hat, aber tatsächlich nichts schreibt). Um das EOF zu senden, lassen Sie den Reserve-Writer weggehen.

mkfifo P
while sleep 1; do :; done >P &
P_writer_pid=$!
send_eof_to_P () {
  kill $P_writer_pid
}

Antwort3

Das Programm kann nicht zwischen einem EOF, das bedeutet „Es ist Zeit aufzuhören“, und einem EOF, das bedeutet „Ein Autor ist fertig, aber es kann sein, dass noch Input von jemand anderem kommt“, unterscheiden.

Wenn Sie die Möglichkeit haben, das Verhalten Ihres Programms zu ändern, führen Sie das Lesen in einer Endlosschleife durch (eine Iteration dauert bis zum EOF) und senden Sie ihm eine bestimmte Befehlszeichenfolge, die „Zeit zum Beenden“ bedeutet. Das Senden dieser Zeichenfolge wäre die Aufgabe des send_eofBefehls in Ihrer Frage.

Andere Option:

( echo some stuff; cat more_stuff.txt ) >P

oder

{ echo some stuff; cat more_stuff.txt; } >P

verwandte Informationen