Wir alle kennen mkfifo
und Pipelines. Der erste erzeugt eine Named Pipe, daher muss man einen Namen auswählen, wahrscheinlich mit mktemp
und später daran denken, die Verknüpfung zu lösen. Der andere erzeugt eine anonyme Pipe, ohne Probleme mit Namen und Entfernung, aber die Enden der Pipe werden mit den Befehlen in der Pipeline verknüpft. Es ist nicht sehr praktisch, die Dateideskriptoren in den Griff zu bekommen und sie im Rest zu verwenden des Skripts. In einem kompilierten Programm würde ich einfach tun ret=pipe(filedes)
; In Bash gibt es exec 5<>file
so etwas wie "exec 5<> -"
oder "pipe <5 >6"
gibt es so etwas in Bash?
38
Während keine der Muscheln, die ich kenne, Rohre ohne Gabelung herstellen kann, haben einige eine bessere als die grundlegende Muschelrohrleitung.
In bash, ksh und zsh können Sie, sofern Ihr System dies unterstützt
/dev/fd
(die meisten heutzutage), die Eingabe oder Ausgabe eines Befehls an einen Dateinamen binden:<(command)
Wird zu einem Dateinamen erweitert, der eine Pipe bezeichnet, die mit der Ausgabe von verbunden istcommand
, und wird>(command)
erweitert auf einen Dateinamen, der eine Pipe bezeichnet, die mit dem Eingang von verbunden istcommand
. Diese Funktion wird als Prozessersetzung bezeichnet . Sein Hauptzweck besteht darin, mehr als einen Befehl in einen anderen oder aus einem anderen heraus zu leiten, z.Dies ist auch nützlich, um einige der Mängel grundlegender Mantelrohre zu bekämpfen. Zum Beispiel
command2 < <(command1)
ist äquivalent zucommand1 | command2
, außer dass sein Status der von istcommand2
. Ein weiterer Anwendungsfall istexec > >(postprocessing)
, dass er dem Rest des Skripts entspricht, aber besser lesbar ist, als es zu tun{ ... } | postprocessing
.quelle
pipe:[123456]
). Emacs stellt fest, dass das Ziel des Symlinks kein vorhandener Dateiname ist und verwirrt genug, dass die Datei nicht gelesen wird (es gibt möglicherweise eine Option, die es veranlasst, die Datei trotzdem zu lesen, obwohl Emacs das Öffnen einer Pipe als nicht mag Datei trotzdem).Bash 4 hat Koprozesse .
quelle
Ab Oktober 2012 scheint diese Funktionalität in Bash noch nicht vorhanden zu sein, aber Coproc kann verwendet werden, wenn Sie nur mit einem untergeordneten Prozess sprechen müssen. Das Problem mit Coproc an dieser Stelle ist, dass anscheinend immer nur einer unterstützt wird. Ich kann nicht herausfinden, warum Coproc diese Einschränkung hat. Sie hätten eine Erweiterung des vorhandenen Hintergrundcodes für Tasks (& op) sein sollen, aber das ist eine Frage für die Autoren von bash.
quelle
coproc THING { dothing; }
Jetzt befinden sich Ihre FDs in der Liste,${THING[*]}
und Sie könnencoproc OTHERTHING { dothing; }
Dinge von und zu beiden ausführen und senden und empfangen.man bash
, unter dem BUGS-Titel, heißt es: Es kann immer nur einen aktiven Coprozess geben . Und Sie erhalten eine Warnung, wenn Sie einen zweiten Coproc starten. Es scheint zu funktionieren, aber ich weiß nicht, was im Hintergrund explodiert.Während die Antwort von @ DavidAnderson alle Grundlagen abdeckt und einige nette Schutzmaßnahmen bietet, ist das Wichtigste, was sich herausstellt , dass es so einfach ist, anonyme Pfeifen in die Hände zu bekommen
<(:)
, solange Sie unter Linux bleiben.Die kürzeste und einfachste Antwort auf Ihre Frage lautet also:
Unter macOS funktioniert es nicht. Dann müssen Sie ein temporäres Verzeichnis erstellen, in dem das benannte FIFO gespeichert wird, bis Sie es umgeleitet haben. Ich weiß nichts über andere BSDs.
quelle
exec
wird und ein anonymes FIFO nur zum Lesen geöffnet wird,exec
darf dieses anonyme FIFO nicht zum Lesen und Schreiben mit einem benutzerdefinierten Dateideskriptor geöffnet werden. Sie sollten damit rechnen, eine-bash: /dev/fd/5: Permission denied
Nachricht zu erhalten, auf die sich macOS bezieht. Ich glaube, der Fehler ist, dass Ubuntu nicht die gleiche Nachricht erzeugt. Ich wäre bereit, meine Meinung zu ändern, wenn jemand Unterlagen vorlegen könnte, aus denen hervorgeht, dass diesexec 5<> <(:)
zulässig ist.open(..., O_RDWR)
ein durch die Substitution bereitgestelltes unidirektionales Pipe-Ende zu bearbeiten und es in einem FD in eine bidirektionale Pipe umzuwandeln. Sie haben wahrscheinlich Recht, dass man sich nicht darauf verlassen sollte. :-D Ausgabe von execline's piperw , um die Pipe zu erstellen, und anschließende Umnutzung mit bash<>
: libranet.de/display/0b6b25a8-195c-84af-6ac7-ee6696661765exec 5<>
, dann gib einfun() { ls -l $1; ls -lH $1; }; fun <(:)
.Die folgende Funktion wurde mit getestet
GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu)
. Das Betriebssystem war Ubuntu 18. Diese Funktion verwendet einen einzelnen Parameter, der der gewünschte Dateideskriptor für das anonyme FIFO ist.Die folgende Funktion wurde mit getestet
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)
. Das Betriebssystem war macOS High Sierra. Diese Funktion erstellt zunächst ein benanntes FIFO in einem temporären Verzeichnis, das nur dem Prozess bekannt ist, der es erstellt hat . Als nächstes wird der Dateideskriptor zum FIFO umgeleitet. Schließlich wird das FIFO vom Dateinamen getrennt, indem das temporäre Verzeichnis gelöscht wird. Dies macht den FIFO anonym.Die oben genannten Funktionen können zu einer einzigen Funktion kombiniert werden, die auf beiden Betriebssystemen funktioniert. Nachfolgend finden Sie ein Beispiel für eine solche Funktion. Hier wird versucht, einen wirklich anonymen FIFO zu erstellen. Wenn dies nicht erfolgreich ist, wird ein benannter FIFO erstellt und in einen anonymen FIFO konvertiert.
Hier ist ein Beispiel für das Erstellen eines anonymen FIFOs und anschließendes Schreiben von Text in dasselbe FIFO.
Nachfolgend finden Sie ein Beispiel für das Lesen des gesamten Inhalts des anonymen FIFO.
Dies erzeugt die folgende Ausgabe.
Mit dem folgenden Befehl wird das anonyme FIFO geschlossen.
Verweise:
Erstellen einer anonymen Pipe für die spätere Verwendung
Dateien in öffentlich beschreibbaren Verzeichnissen sind eine gefährliche
Shell-Skriptsicherheit
quelle
Unter Verwendung der großartigen und hellen Antwort von htamas habe ich sie ein wenig modifiziert, um sie in einem Einzeiler zu verwenden. Hier ist sie:
quelle