Normalerweise hat ein erschöpftes Rohr beim Arbeiten mit Rohren und Standardleitungen keine besondere Bedeutung. Neue Daten werden möglicherweise weiterhin angezeigt, bis eof
die Pipe geschlossen wird. Sie cat
endet eof
wie erwartet. Wenn es vor keine Daten sind eof
, nur dann können Sie die stdin sagen waren wirklich leer.
Betrachten sender | receiver
. Es ist nicht ungewöhnlich, dass das sender
(viel) langsamer ist als das receiver
; In diesem Fall ist der receiver
Standardwert fast immer erschöpft, aber Sie möchten fast nie die gesamte Pfeife töten. Daher sind Werkzeuge, die auf "empty" (erschöpft, aber noch nicht beendet) stdin stehen, eher Ausnahmen als Standard.
In Bash gibt es read -t 0
( -t
wird von POSIX nicht benötigt). Von help read
:
Wenn
TIMEOUT
ist0
,read
kehrt sofort zurück, ohne zu versuchen, alle Daten zu lesen, Erfolg Rückkehr nur, wenn der Eingang auf dem angegebenen Dateideskriptor verfügbar ist.
Standardmäßig wird read
von stdin gelesen. Der Exit-Status von read -t 0
sagt Ihnen dann, ob der stdin "leer" ist. Aber Vorsicht! Ein Befehl wie
echo 1 | read -t 0
kann erfolgreich beendet werden oder nicht, weil echo
und read
gleichzeitig ausgeführt werden, nicht sequentiell. Um dies zu vermeiden, sollte Ihr Skript sleep
vorher eine Weile dauern read -t 0
. Abhängig davon, woher der Standard kommt, kann "eine Weile" relativ lang sein. Tun Sie so etwas:
sleep 1 if read -t 0; then … # process stdin here, you know it's non-empty
Sie füllen eine Variable mit Daten aus stdin. Da das Speichern von binären Daten in einer Variablen keine gute Idee ist (lesen Sie dies ), sind Ihre Daten möglicherweise nur Text. Wenn ja, so verwenden read -t
:
read -r -t 5 -d $'\0' stdin
Ein Nullzeichen (das Sie in einer Bash-Variablen sowieso nicht speichern können) als Trennzeichen ( -d $'\0'
) ermöglicht Ihnen das Lesen von Text (z. B. mit Zeilenumbrüchen) der stdin
Variablen. Nach höchstens 5 Sekunden ( -t 5
) wird der Befehl beendet, damit das Skript fortgesetzt werden kann.
Ein anderer Ansatz ist mit timeout
. Ein grundlegendes Beispiel aus meinem Debian:
timeout --foreground 5 cat | wc -c
(Ersetzen Sie wc -c
durch Ihren Code, der stdin parst; es ist nur ein Beispiel).
Dies sollte gut mit binären Daten umgehen. Wenn cat
nicht, eof
dann nach 5 Sekunden, wird es getötet, so wc
wird es eof
trotzdem und die Linie bleibt stehen. Das Problem ist cat
, dass das Problem beendet wird, unabhängig davon, ob gerade Daten verarbeitet werden. Ich kann mir vorstellen, dass Sie alle Daten erhalten möchten, wenn nur einige vorhanden sind, selbst wenn dies mehr als 5 Sekunden dauert. Verbesserte Version:
{ timeout --foreground 5 dd bs=1 count=1 2>/dev/null && cat; } | wc -c
Wenn das erste Byte innerhalb von 5 Sekunden erscheint, cat
wird es ausgelöst. Es werden dann alle weiteren Eingaben verarbeitet eof
, unabhängig davon, wie lange es dauert. Alles, einschließlich des ersten Bytes (falls vorhanden) wird zu gehen wc
. Wenn es weder ein Byte noch eof
in 5 Sekunden gibt, wc
erhalten Sie nur eof
; Die Linie bleibt stehen.