GNU/Linux >> Tutoriels Linux >  >> Linux

Création de fichier temporaire vs substitution de processus vs expansion de variable ?

<(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.


Linux
  1. Filtrage de tcpdump :Créer de l'ordre à partir du chaos

  2. Création d'un fichier CSR de certificat Web.

  3. Substitution de processus et tuyau ?

  4. Créer un fichier vide ayant un nom de variable dans un script ?

  5. Substitution de variable d'environnement dans sed

Définir une variable avec ou sans export

Exclure le répertoire lors de la création d'un fichier .tar.gz

Créer un démon sous Linux

xauth ne crée pas de fichier .Xauthority

Trouver quel processus modifie un fichier

Vider la mémoire d'un processus Linux dans un fichier