GNU/Linux >> Tutoriels Linux >  >> Linux

La méthode portable (posix) pour réaliser la substitution de processus ?

Certains shells, comme bash , prend en charge la substitution de processus qui est un moyen de présenter la sortie du processus sous forme de fichier, comme ceci :

$ diff <(sort file1) <(sort file2)

Cependant, cette construction n'est pas POSIX et, par conséquent, n'est pas portable. Comment la substitution de processus peut-elle être réalisée d'une manière compatible avec POSIX (c'est-à-dire celui qui fonctionne dans /bin/sh )  ?

remarque :la question ne demande pas comment différencier deux fichiers triés - ce n'est qu'un exemple artificiel pour démontrer la substitution de processus !

Réponse acceptée :

Cette fonctionnalité a été introduite par ksh (documenté pour la première fois dans ksh86) et utilisait le /dev/fd/n fonctionnalité
(ajoutée indépendamment dans certains systèmes BSD et AT&T plus tôt).
En ksh et jusqu'à ksh93u, cela ne fonctionnerait que si votre système prenait en charge /dev/fd/n . zsh, bash et ksh93u+ et au-dessus peuvent utiliser des canaux nommés temporaires (canaux nommés ajoutés dans le système III) où /dev/fd/n ne sont pas disponibles.

Sur les systèmes où /dev/fd/n est disponible (POSIX ne les spécifie pas),
vous pouvez effectuer une substitution de processus (par exemple, diff <(cmd1) <(cmd2) ) vous-même avec :

{
  cmd1 4<&- | {
    # in here fd 3 points to the reading end of the pipe
    # from cmd1, while fd 0 has been restored from the original
    # stdin (saved on fd 4, now closed as no longer needed)

    cmd2 3<&- | diff /dev/fd/3 -

  } 3<&0 <&4 4<&- # restore the original stdin for cmd2

} 4<&0 # save a copy of stdin for cmd2

Cependant cela ne fonctionne pas avec ksh93 sous Linux comme là-bas, les canaux shell sont implémentés avec des paires de sockets au lieu de tuyaux et ouvrent /dev/fd/3 où fd 3 pointe vers un socket ne fonctionne pas sous Linux.

Bien que POSIX ne spécifie pas /dev/fd/n , il spécifie des canaux nommés. Les canaux nommés fonctionnent comme des canaux normaux, sauf que vous pouvez y accéder à partir du système de fichiers. Le problème ici est que vous devez en créer des temporaires et les nettoyer ensuite, ce qui est difficile à faire de manière fiable, d'autant plus que POSIX n'a ​​pas de mécanisme standard (comme un mktemp -d comme on en trouve sur certains systèmes) pour créer des fichiers ou des répertoires temporaires, et la gestion du signal (pour nettoyer au raccrochage ou à l'arrêt) est également difficile à faire de manière portable.

Vous pourriez faire quelque chose comme :

tmpfifo() (
  n=0
  until
    fifo=$1.$$.$n
    mkfifo -m 600 -- "$fifo" 2> /dev/null
  do
    n=$((n + 1))
    # give up after 20 attempts as it could be a permanent condition
    # that prevents us from creating fifos. You'd need to raise that
    # limit if you intend to create (and use at the same time)
    # more than 20 fifos in your script
    [ "$n" -lt 20 ] || exit 1
  done
  printf '%s\n' "$fifo"
)

cleanup() { rm -f -- "$fifo"; }

fifo=$(tmpfifo /tmp/fifo) || exit

cmd2 > "$fifo" & cmd1 | diff - "$fifo"

cleanup

(ne pas s'occuper du traitement du signal ici).

Connexe :Processus terminé immédiatement après l'ouverture du terminal et impossible d'ajouter des commandes ?
Linux
  1. Comment mettre à niveau vers Linux Mint 20.3 :la bonne manière

  2. Existe-t-il un moyen de modifier les variables d'environnement d'un autre processus sous Unix ?

  3. Quelle est la définition d'une session sous Linux?

  4. Existe-t-il un moyen d'écouter le processus ?

  5. Comment récupérer par programmation le GID d'un processus en cours d'exécution

Personnaliser Grub en toute simplicité :Grub-customizer

SIGTERM vs SIGKILL :Quelle est la différence ?

Substitution de processus :une méthode peu courante mais avancée pour la redirection d'entrée/sortie sous Linux

Installez Postman Ubuntu 18.04 :le moyen le plus simple !

Quelle est la signification de POSIX ?

Quel est le moyen le plus sûr et le plus portable d'invoquer le binaire echo ?