Nous le savons tous mkfifo
et les pipelines. Le premier crée un canal nommé , il faut donc sélectionner un nom, très probablement avec mktemp
et plus tard, n'oubliez pas de dissocier. L'autre crée un canal anonyme, sans tracas avec les noms et la suppression, mais les extrémités du canal sont liées aux commandes dans le pipeline, il n'est pas vraiment pratique de saisir les descripteurs de fichiers et de les utiliser dans le reste du script. Dans un programme compilé, je ferais juste ret=pipe(filedes)
; dans Bash, il y a exec 5<>file
donc quelque chose à attendre "exec 5<> -"
ou "pipe <5 >6"
quelque chose comme ça dans Bash?
38
Bien qu'aucun des obus que je connaisse ne puisse fabriquer des tuyaux sans bifurquer, certains ont mieux que le pipeline de base.
En bash, ksh et zsh, en supposant que votre système prend en charge
/dev/fd
(la plupart le font de nos jours), vous pouvez lier l'entrée ou la sortie d'une commande à un nom de fichier: se<(command)
développe en un nom de fichier qui désigne un tuyau connecté à la sortie decommand
, et se>(command)
développe à un nom de fichier qui désigne un tuyau connecté à l'entrée decommand
. Cette fonctionnalité est appelée substitution de processus . Son objectif principal est de diriger plusieurs commandes vers une autre ou vers une autre, par exemple,Ceci est également utile pour lutter contre certaines des lacunes des tuyaux shell de base. Par exemple,
command2 < <(command1)
est équivalent àcommand1 | command2
, sauf que son statut est celui decommand2
. Un autre cas d'utilisation estexec > >(postprocessing)
, ce qui équivaut à, mais plus lisible que, de mettre tout le reste du script à l'intérieur{ ... } | postprocessing
.la source
pipe:[123456]
). Emacs voit que la cible du lien symbolique n'est pas un nom de fichier existant et cela le confond suffisamment pour qu'il ne lise pas le fichier (il peut y avoir une option pour le faire lire de toute façon, bien qu'Emacs n'aime pas ouvrir un tube en tant que fichier quand même).Bash 4 a des coprocessus .
la source
Depuis octobre 2012, cette fonctionnalité ne semble toujours pas exister dans Bash, mais coproc peut être utilisé si tout ce dont vous avez besoin pour des canaux sans nom / anonymes est de parler à un processus enfant. Le problème avec coproc à ce stade est que, apparemment, un seul est pris en charge à la fois. Je ne peux pas comprendre pourquoi coproc a cette limitation. Ils auraient dû être une amélioration du code d'arrière-plan de tâche existant (le & op), mais c'est une question pour les auteurs de bash.
la source
coproc THING { dothing; }
maintenant vos FD sont dedans${THING[*]}
et vous pouvez exécutercoproc OTHERTHING { dothing; }
et envoyer et recevoir des choses vers et depuis les deux.man bash
, sous le titre BUGS, ils disent ceci: Il ne peut y avoir qu'un seul coprocessus actif à la fois . Et vous obtenez un avertissement si vous démarrez un deuxième coproc. Cela semble fonctionner, mais je ne sais pas ce qui explose en arrière-plan.Alors que la réponse de @ DavidAnderson couvre toutes les bases et offre de belles garanties, la chose la plus importante qu'elle révèle est qu'il est aussi facile de mettre la main sur un canal anonyme
<(:)
, tant que vous restez sur Linux.La réponse la plus courte et la plus simple à votre question est donc:
Sur macOS, cela ne fonctionnera pas, alors vous devrez créer un répertoire temporaire pour héberger le fifo nommé jusqu'à ce que vous y soyez redirigé. Je ne connais pas les autres BSD.
la source
exec
est passé et fifo anonyme qui est ouvert uniquement pour la lecture, alorsexec
ne devrait pas permettre à ce fifo anonyme d'être ouvert pour la lecture et l'écriture à l'aide d'un descripteur de fichier personnalisé. Vous devez vous attendre à recevoir un-bash: /dev/fd/5: Permission denied
message, ce qui est le problème de macOS. Je pense que le bogue est qu'Ubuntu ne produit pas le même message. Je serais prêt à changer d'avis si quelqu'un pouvait produire des documents disant que lesexec 5<> <(:)
explications sont autorisées.open(..., O_RDWR)
sur une extrémité de tuyau unidirectionnelle fournie par la substitution et qui le transforme en tuyau bidirectionnel dans un FD. Vous avez probablement raison de ne pas vous fier à cela. :-D Sortie de l'utilisation du piperw d'execline pour créer le tuyau, puis le réaffecter avec bash<>
: libranet.de/display/0b6b25a8-195c-84af-6ac7-ee6696661765exec 5<>
, entrezfun() { ls -l $1; ls -lH $1; }; fun <(:)
.La fonction suivante a été testée en utilisant
GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu)
. Le système d'exploitation était Ubuntu 18. Cette fonction prend un seul paramètre qui est le descripteur de fichier souhaité pour le FIFO anonyme.La fonction suivante a été testée en utilisant
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)
. Le système d'exploitation était macOS High Sierra. Cette fonction démarre en créant un FIFO nommé dans un répertoire temporaire connu uniquement du processus qui l'a créé . Ensuite, le descripteur de fichier est redirigé vers le FIFO. Enfin, le FIFO est dissocié du nom de fichier en supprimant le répertoire temporaire. Cela rend le FIFO anonyme.Les fonctions ci-dessus peuvent être combinées en une seule fonction qui fonctionnera sur les deux systèmes d'exploitation. Voici un exemple d'une telle fonction. Ici, une tentative est faite pour créer un FIFO vraiment anonyme. En cas d'échec, un FIFO nommé est créé et converti en FIFO anonyme.
Voici un exemple de création d'un FIFO anonyme, puis d'écriture de texte dans le même FIFO.
Vous trouverez ci-dessous un exemple de lecture de l'intégralité du contenu de la FIFO anonyme.
Cela produit la sortie suivante.
La commande ci-dessous ferme le FIFO anonyme.
Références: la
création d'un canal anonyme pour une utilisation ultérieure Les
fichiers dans les répertoires accessibles en écriture sont une sécurité de script shell dangereuse
la source
En utilisant la bonne et brillante réponse de htamas, je l'ai un peu modifiée pour l'utiliser dans une doublure, la voici:
la source