Ils sont étendus par processus
Les autres intervenants m'ont aidé à comprendre que la portée des variables shell concerne les processus et leurs descendants .
Lorsque vous tapez une commande comme ls
sur la ligne de commande, vous êtes en train de forger un processus pour exécuter le ls
programme. Le nouveau processus a votre shell comme parent.
Tout processus peut avoir ses propres variables "locales", qui ne sont pas transmises aux processus enfants. Il peut également définir des variables "d'environnement", qui sont. Utiliser export
crée une variable d'environnement. Dans les deux cas, les processus indépendants (homologues de l'original) ne verront pas la variable. nous ne contrôlons que ce que les processus enfants voient.
Supposons que vous ayez un shell bash, que nous appellerons A. Vous tapez bash
, ce qui crée un shell bash de processus enfant, que nous appellerons B. Tout ce que vous avez appelé export
en A sera toujours défini en B.
Maintenant, en B, vous dites FOO=b
. Une des deux choses va se passer:
- Si B n'a pas reçu (de A) une variable d'environnement appelée
FOO
, il créera une variable locale. Les enfants de B ne l’auront pas (à moins que B n’appelle export
).
- Si B a effectivement reçu (de A) une variable d’environnement appelée
FOO
, il la modifiera pour elle-même et ses enfants ensuite créés . Les enfants de B verront la valeur attribuée par B. Cependant, cela n'affectera pas du tout A.
Voici une démo rapide.
FOO=a # set "local" environment variable
echo $FOO # 'a'
bash # forks a child process for the new shell
echo $FOO # not set
exit # return to original shell
echo $FOO # still 'a'
export FOO # make FOO an environment variable
bash # fork a new "child" shell
echo $FOO # outputs 'a'
FOO=b # modifies environment (not local) variable
bash # fork "grandchild" shell
echo $FOO # outputs 'b'
exit # back to child shell
exit # back to original shell
echo $FOO # outputs 'a'
Tout cela explique mon problème initial: je me suis installé GEM_HOME
dans mon shell, mais lorsque j'ai appelé bundle install
, cela a créé un processus enfant. Parce que je n'avais pas utilisé export
, le processus enfant n'a pas reçu le shell GEM_HOME
.
Exportation
Vous pouvez "dés-exporter" une variable - en l'empêchant d'être transmise aux enfants - en utilisant export -n FOO
.
export FOO=a # Set environment variable
bash # fork a shell
echo $FOO # outputs 'a'
export -n FOO # remove environment var for children
bash # fork a shell
echo $FOO # Not set
exit # back up a level
echo $FOO # outputs 'a' - still a local variable
FOO=bar
, cela définit la valeur du processus shell en cours. Si je lance ensuite un programme comme (bundle install
), cela crée un processus enfant, auquel il n’a pas accèsFOO
. Mais si j'avais ditexport FOO=bar
, le processus enfant (et ses descendants) y auraient accès. L'un d'eux pourrait, à son tour, appelerexport FOO=buzz
pour changer la valeur pour ses descendants, ou simplementFOO=buzz
pour changer la valeur uniquement pour elle-même. Est-ce à peu près correct?