web-dev-qa-db-fra.com

Si les processus héritent de l'environnement du parent, pourquoi avons-nous besoin d'exporter?

J'ai lu ici que le but de export dans un Shell est de rendre la variable disponible pour les sous-processus démarrés à partir du Shell.

Cependant, j'ai également lu ici et ici que "Les processus héritent de leur environnement de leur parent (le processus qui les a démarrés)."

Si tel est le cas, pourquoi avons-nous besoin de export? Qu'est-ce que je rate?

Les variables Shell ne font-elles pas partie de l'environnement par défaut? Quelle est la différence?

75

Votre hypothèse est que les variables Shell sont dans l'environnement. Ceci est une erreur. La commande export est ce qui définit un nom comme étant dans l'environnement. Donc:

a=1 b=2
export b

résulte dans le courant Shell sachant que $a se développe en 1 et $b en 2, mais les sous-processus ne sauront rien de a parce qu'il n'est pas une partie de l'environnement (même dans le Shell actuel).

Quelques outils utiles:

  • set: utile pour visualiser les paramètres actuels du Shell, exportés ou non
  • set -k: Définit arguments assignés dans l'environnement. Considérez f() { set -k; env; }; f a=1
  • set -a: Indique au shell de mettre n'importe quel nom défini dans l'environnement. Comme mettre export avant chaque affectation. Utile pour les fichiers .env, Comme dans set -a; . .env; set +a.
  • export: indique au shell de mettre un nom dans l'environnement. L'exportation et l'affectation sont deux opérations entièrement différentes.
  • env: En tant que commande externe, env ne peut que vous renseigner sur l'environnement hérité, il est donc utile pour la vérification d'intégrité.
  • env -i: Utile pour effacer l'environnement avant de démarrer un sous-processus.

Alternatives à export:

  1. name=val command # Affectation avant que la commande exporte ce nom vers la commande.
  2. declare/local -x name # Exporte le nom, particulièrement utile dans les fonctions Shell lorsque vous voulez éviter d'exposer le nom à une portée extérieure.
  3. set -a # Exporte toutes les affectations suivantes.
79
kojiro

Il y a une différence entre les variables Shell et les variables d'environnement. Si vous définissez une variable Shell sans exporting, elle n'est pas ajoutée à l'environnement de processus et n'est donc pas héritée de ses enfants.

En utilisant export, vous dites au Shell d'ajouter la variable Shell à l'environnement. Vous pouvez tester cela en utilisant printenv (qui imprime simplement son environnement dans stdout, car c'est un processus enfant dont vous voyez l'effet des exporting variables):

#!/bin/sh

MYVAR="my cool variable"

echo "Without export:"
printenv | grep MYVAR

echo "With export:"
export MYVAR
printenv | grep MYVAR
24
Andreas Wiese

Une variable, une fois exportée, fait partie de l'environnement. PATH est exporté dans le shell lui-même, tandis que les variables personnalisées peuvent être exportées selon les besoins. En utilisant un code d'installation:

$ cat subshell.sh 
#!/usr/bin/env bash
declare | grep -e '^PATH=' -e '^foo='

Comparer

$ cat test.sh 
#!/usr/bin/env bash
export PATH=/bin
export foo=bar
declare | grep -e '^PATH=' -e '^foo='
./subshell.sh
$ ./test.sh 
PATH=/bin
foo=bar
PATH=/bin
foo=bar

Avec

$ cat test2.sh 
#!/usr/bin/env bash
PATH=/bin
foo=bar
declare | grep -e '^PATH=' -e '^foo='
./subshell.sh
$ ./test2.sh 
PATH=/bin
foo=bar
PATH=/bin

Puisque foo n'est pas exporté par le shell et test2.sh ne l'a jamais exporté, il ne faisait pas partie de l'environnement de subshell.sh lors de la dernière exécution.

6
l0b0