<(cmd)
est un ksh
fonctionnalité également trouvée de nos jours dans zsh
et bash
appelé substitution de processus .
Sur les systèmes prenant en charge /dev/fd/n
ou /proc/self/fd/n
, il est implémenté avec des canaux et lorsqu'il n'est pas avec des canaux nommés temporaires. Dans tous les cas, c'est une forme de pipe qui est un mécanisme de communication interprocessus.
cmd1 <(cmd2)
Peut s'écrire (avec des tubes normaux) :
{ cmd2 4<&- | 3<&0 <&4 4<&- cmd1 /dev/fd/3; } 4<&0
Ou (avec des canaux nommés) :
mkfifo /tmp/named_pipe
cmd2 > /tmp/named_pipe & cmd1 /tmp/named_pipe
C'est-à-dire que les deux commandes sont lancées simultanément et communiquent avec un tube. Vous utiliseriez généralement cmd2 | cmd1
pour cela, mais la substitution de processus concerne généralement les cas où cmd1
ne peut prendre d'entrée qu'à partir d'un nom de fichier et non à partir d'une entrée standard ou lorsque plusieurs entrées sont nécessaires comme dans diff <(cmd1) <(cmd2)
.
Il n'y a pas de limite qui l'affecte autre que les limites générales comme le nombre de processus, le temps CPU ou la mémoire.
Le PIPEBUF signalé par certaines implémentations de ulimit
comme bash
et quelques implémentations de ksh
n'est pas une rlimit mais la taille maximale pour laquelle une écriture dans un tube est garantie d'être atomique n'est donc pas pertinente ici. La taille du tuyau lui-même (64 Ko sous Linux, tel que rapporté par @dsmsk80) n'est pas vraiment une limite en soi. Ça dit juste que c'est autant cmd2
peut écrire dans le tube même après cmd1
a cessé de lire à partir de celui-ci.
Il y a cependant une limitation dans ce cmd1
peut seulement lire à partir de ce fichier. Parce qu'il s'agit d'un tube, il ne peut pas écrire dans ce fichier ou effectuer des allers-retours dans le fichier.
zsh
a une troisième forme de substitution de commande utilisant des fichiers temporaires réguliers :
cmd1 =(cmd2)
appelle le cmd1
avec un fichier temporaire qui contient la sortie de cmd2
. Dans ce cas cmd1
est exécuté après cmd2 au lieu de simultanément. La limite de taille des fichiers peut y être atteinte.
Je ne connais aucun shell implémentant un <<<(...)
opérateur. Il y a cependant un <<<
opérateur en zsh
(inspiré du même opérateur dans le port Unix de rc
) également trouvé dans les versions récentes de ksh93
et bash
. C'est une variante du <<
opérateur heredoc appelé herestring.
Dans :
cmd <<< something
Qui est identique à la norme :
cmd << EOF
something
EOF
Le shell crée un fichier temporaire avec something\n
comme contenu et flux comme entrée standard d'un nouveau processus, dissocie ce fichier et exécute cmd
dans ce nouveau processus. Encore une fois, c'est un fichier normal, donc la limite de taille maximale d'un fichier peut être atteinte.
Vous pouvez maintenant combiner le <<<
opérateur avec $(...)
(substitution de commande) pour émuler en quelque sorte zsh
est =(...)
opérateur en bash
et ksh93
:
cmd1 <<<"$(cmd2)"
Exécuterait cmd2
avec elle stdout redirigé vers un tuyau. À l'autre bout du tuyau, le shell lit la sortie de cmd2
et le stocke moins les caractères de fin de ligne et avec un caractère de nouvelle ligne ajouté dans un fichier temporaire et appelez cmd1
avec ce fichier temporaire ouvert pour la lecture en tant que stdin (notez qu'il y a une autre limitation en ce sens que cela ne fonctionnera pas si cmd2
la sortie contient des caractères NUL).
Être comme =(...)
, il faudrait l'écrire :
cmd1 /dev/fd/3 3<<<"$(cmd3)"
Notez que le shell doit lire toute la sortie de cmd3 en mémoire avant de l'écrire dans le fichier temporaire, donc en plus de la taille maximale du fichier, vous pouvez également atteindre la limite d'utilisation de la mémoire.
Notez également que depuis la version 5, bash
supprime les autorisations d'écriture sur le fichier temporaire avant d'appeler cmd1
, donc si vous avez besoin de cmd1
pour pouvoir modifier ce fichier, vous devez le contourner avec :
{
chmod u+w /dev/fd/3 && # only needed in bash 5+
cmd1 /dev/fd/3
} 3<<<"$(cmd3)"
Substitution du processus Bash sous la forme de <(cmd)
et >(cmd)
est implémenté avec des canaux nommés si le système les prend en charge. La commande cmd
est exécuté avec son entrée/sortie connectée à un tuyau. Lorsque vous courez par ex. cat <(sleep 10; ls)
vous pouvez trouver le tube créé sous le répertoire /proc/pid_of_cat/fd
. Ce tube nommé est ensuite passé en argument à la commande en cours (cat
).
La capacité tampon d'un tuyau peut être estimée avec une utilisation délicate de dd
commande qui envoie des données nulles à l'entrée standard de sleep
commande (qui ne fait rien). Apparemment, le processus va dormir un certain temps pour que le tampon soit plein :
(dd if=/dev/zero bs=1 | sleep 999) &
Donnez-lui une seconde, puis envoyez USR1
signal au dd
processus :
pkill -USR1 dd
Cela rend le processus d'impression des statistiques d'E/S :
65537+0 records in
65536+0 records out
65536 bytes (66 kB) copied, 8.62622 s, 7.6 kB/s
Dans mon cas de test, la taille du tampon est 64kB
(65536B
).
Comment utilisez-vous <<<(cmd)
expansion? Je suis conscient qu'il s'agit d'une variante d'ici les documents qui sont développés et transmis à la commande sur son entrée standard.
J'espère avoir éclairci la question de la taille. En ce qui concerne la vitesse, je ne suis pas si sûr, mais je suppose que les deux méthodes peuvent fournir un débit similaire.