GNU/Linux >> Tutoriels Linux >  >> Linux

Les parenthèses placent-elles vraiment la commande dans un sous-shell ?

D'après ce que j'ai lu, mettre une commande entre parenthèses devrait l'exécuter dans un sous-shell, similaire à l'exécution d'un script. Si c'est vrai, comment voit-il la variable x si x n'est pas exporté ?

x=1

Exécution de (echo $x) sur la ligne de commande donne 1

Exécution de echo $x dans un script ne donne rien, comme prévu

Réponse acceptée :

Un sous-shell commence comme une copie presque identique du processus shell d'origine. Sous le capot, le shell appelle le fork appel système, qui crée un nouveau processus dont le code et la mémoire sont des copies. Lorsque le sous-shell est créé, il y a très peu de différences entre lui et son parent. En particulier, ils ont les mêmes variables. Même le $$ La variable spéciale conserve la même valeur dans les sous-shells :c'est l'ID de processus du shell d'origine. De même $PPID est le PID du parent du shell d'origine.

Quelques shells modifient quelques variables dans le sous-shell. Bash définit BASHPID au PID du processus shell, qui change dans les sous-shells. Bash, zsh et mksh s'arrangent pour $RANDOM pour produire des valeurs différentes dans le parent et dans le sous-shell. Mais en dehors des cas spéciaux intégrés comme ceux-ci, toutes les variables ont la même valeur dans le sous-shell que dans le shell d'origine, le même statut d'exportation, le même statut de lecture seule, etc. Toutes les définitions de fonction, les définitions d'alias, les options du shell et d'autres paramètres sont également hérités.

Un sous-shell créé par (…) a les mêmes descripteurs de fichier que son créateur. D'autres moyens de créer des sous-interpréteurs modifient certains descripteurs de fichiers avant d'exécuter le code utilisateur ; par exemple, le côté gauche d'un tuyau s'exécute dans un sous-shell avec une sortie standard connectée au tuyau. Le sous-shell démarre également avec le même répertoire courant, le même masque de signal, etc. L'une des rares exceptions est que les sous-shells n'héritent pas des traps personnalisés :signaux ignorés (trap '' SIGNAL ) restent ignorés dans le sous-shell, mais d'autres traps (trap CODE SIGNAL ) sont réinitialisés à l'action par défaut.

Un sous-shell est donc différent de l'exécution d'un script. Un script est un programme séparé. Ce programme séparé pourrait par coïncidence être aussi un script qui est exécuté par le même interpréteur que le parent, mais cette coïncidence ne donne pas au programme séparé une visibilité particulière sur les données internes du parent. Les variables non exportées sont des données internes, donc lorsque l'interpréteur du script shell enfant est exécuté, il ne voit pas ces variables. Les variables exportées, c'est-à-dire les variables d'environnement, sont transmises aux programmes exécutés.

Ainsi :

x=1
(echo $x)

imprime 1 car le sous-shell est une réplique du shell qui l'a engendré.

x=1
sh -c 'echo $x'

arrive à exécuter un shell en tant que processus enfant d'un shell, mais le x sur la deuxième ligne n'a plus de rapport avec le x sur la deuxième ligne que dans

x=1
perl -le 'print $x'

ou

x=1
python -c 'print x'

Une exception est le ksh93 shell où le forking est optimisé et la plupart de ses effets secondaires sont émulés.
Sémantiquement, ce sont des copies. Du point de vue de la mise en œuvre, il y a beaucoup de partage en cours.
Pour le côté droit, cela dépend du shell.
Si vous testez ceci, notez que des choses comme $(trap) peut signaler les pièges de la coque d'origine. Notez également que de nombreux shells ont des bogues dans les cas de coin impliquant des pièges. Par exemple, ninjalj note qu'à partir de bash 4.3, bash -x -c 'trap "echo ERR at $BASH_SUBSHELL $BASHPID" ERR; set -E; false; echo one subshell; (false); echo two subshells; ( (false) )' exécute le ERR trap du sous-shell imbriqué dans le cas "deux sous-shells", mais pas le ERR trap du sous-shell intermédiaire — set -E l'option doit propager le ERR trap à tous les sous-shells mais le sous-shell intermédiaire est optimisé et n'est donc pas là pour exécuter son ERR piège.

En relation:Linux - Pourquoi setuid ne fonctionne-t-il pas ??
Linux
  1. Maîtrisez la commande Linux ls

  2. Comment affecter la sortie d'une commande à une variable Shell ?

  3. Comment puis-je boucler sur la sortie d'une commande shell ?

  4. Que signifie la syntaxe |&en langage shell ?

  5. Exécutez un script shell à partir de la commande docker-compose, à l'intérieur du conteneur

Commande source sous Linux

Qu'est-ce que le Shell sous Linux ?

Interface de commandes

Quelle est la différence entre obtenir la sortie de la commande en utilisant `command` et $ (commande) dans Shell ??

Personnalisation de Bash Shell :Gras/couleur La commande ?

Commande Bash fc :utilisez facilement le shell Bash comme un pro