En zsh, différence entre cat <(cat) vs cat | chat vs chat = (chat)?

18

Je m'y attendais cat <(cat)et cat | catde faire la même chose: copier des lignes de stdin stdout. Ma compréhension était que les deux exécuteraient un catdans un sous-shell, redirigeraient la sortie catstandard du sous-shell vers un tube nommé temporaire, puis en exécuteraient un autre catdans le shell actuel avec son stdin redirigé vers le tube.

Au lieu de cela, cat <(cat)permet de taper sur mon terminal, mais aucune des lignes d'entrée n'est copiée et ^Dne parvient pas à signaler EOF; cat | catfonctionne comme prévu cependant.

Comme une autre expérience, j'ai vérifié si cat =(cat)a des difficultés similaires cat <(cat), mais cela fonctionne comme prévu: tous les stdin jusqu'à un ^Dsont copiés dans stdout en une seule fois.

Quelqu'un peut-il m'aider à comprendre ce que zsh fait sous le capot?

Alan O'Donnell
la source

Réponses:

23
  1. a | bse connecte STDOUTdepuis aet STDINdepuis bsimplement en utilisant dup/dup2. Les deux commandes sont exécutées en parallèle.

  2. a =(b)remplace l'argument to apar un nom de fichier temporaire. bsera exécuté avant acar le fichier temporaire doit être créé avant de pouvoir être transmis àa

  3. a <(b)remplace l'argument to apar un canal nommé. aet bfonctionner en parallèle. C'est maintenant que cela devient un peu compliqué:

    best en arrière-plan et ne peut pas lire depuis le terminal. Vous pouvez le tester vous-même en utilisant strace -p $PIDpour attacher à votre deuxième processus de chat pour voir le processus.

    aen attendant, essaie de lire à partir du canal nommé mais ne peut rien lire car as bne peut pas lire.

    • Cela signifie que vous avez fondamentalement un blocage où aessaie de lire bmais bne peut pas lire STDINet ne peut pas écrire dansa

Plus d'informations sur le processus d'arrière-plan et le terminal de man bash :

Pour faciliter la mise en œuvre de l'interface utilisateur pour le contrôle des travaux, le système d'exploitation conserve la notion d' ID de groupe de processus terminal actuel . Les membres de ce groupe de processus (processus dont l'ID de groupe de processus est égal à l'ID de groupe de processus terminal actuel) reçoivent des signaux générés par le clavier tels que SIGINT . Ces processus seraient au premier plan . Contexteles processus sont ceux dont l'ID de groupe de processus diffère de celui du terminal; ces processus sont immunisés contre les signaux générés par le clavier. Seuls les processus de premier plan sont autorisés à lire ou, si l'utilisateur le souhaite avec stty tostop, à écrire sur le terminal. Les processus en arrière-plan qui tentent de lire (écrire sur quand stty tostop est en vigueur) le terminal reçoivent un signal SIGTTIN (SIGTTOU) par le pilote de terminal du noyau, qui, à moins qu'il ne soit intercepté, suspend le processus.

Ulrich Dangel
la source
Super, merci - cela a beaucoup éclairci!
Alan O'Donnell
1
Notez que lorsqu'il n'est pas interactif, zsh redirige l'entrée standard des commandes d' arrière - plan (y compris celles en <(cmd)) vers /dev/null, de sorte que le comportement diffère ( zsh -c 'cat <(cat)'retourne immédiatement et ne produit rien).
Stéphane Chazelas