À quoi sert export
?
Quelle est la différence entre:
export name=value
et
name=value
export
rend la variable disponible pour les sous-processus.
C'est,
export name=value
signifie que le nom de la variable est disponible pour tout processus vous exécutez à partir de ce processus Shell. Si vous souhaitez qu'un processus utilise cette variable, utilisez export
et exécutez le processus à partir de ce shell.
name=value
signifie que la portée de la variable est limitée au shell et n'est disponible pour aucun autre processus. Vous utiliseriez ceci pour (par exemple) des variables de boucle, des variables temporaires, etc.
Il est important de noter que l'exportation d'une variable ne la rend pas disponible pour les processus parents. Autrement dit, spécifier et exporter une variable dans un processus généré ne la rend pas disponible dans le processus qui l'a lancée.
Pour illustrer ce que disent les autres réponses:
$ foo="Hello, World"
$ echo $foo
Hello, World
$ bar="Goodbye"
$ export foo
$ bash
bash-3.2$ echo $foo
Hello, World
bash-3.2$ echo $bar
bash-3.2$
D'autres ont répondu que l'export rend la variable disponible pour les sous-réservoirs, ce qui est correct, mais simplement un effet secondaire. Lorsque vous exportez une variable, cette variable est placée dans l'environnement du shell actuel (le shell appelle putenv (3) ou setenv (3)). L'environnement d'un processus est hérité à travers exec, rendant la variable visible dans les sous-shell.
Edit (avec une perspective de 5 ans): c’est une réponse idiote. Le but de 'export' est de créer des variables "dans l'environnement des commandes exécutées ultérieurement", que ces commandes soient des sous-shell ou des sous-processus. Une implémentation naïve consisterait simplement à placer la variable dans l'environnement de Shell, mais cela rendrait impossible la mise en œuvre de export -p
.
On a dit qu’il n’était pas nécessaire d’exporter en bash lors du frai de sous-coquilles, alors que d’autres disaient exactement le contraire. Il est important de noter la différence entre les sous-shell (ceux créés par ()
, ``
, $()
ou les boucles) et les sous-processus (processus appelés par leur nom, par exemple un bash
littéral apparaissant dans votre script).
Ce qui est commun dans ces deux constructions est qu’aucune d’entre elles ne peut transmettre de variables au Shell parent.
$ noexport=noexport; export export=export; (echo subshell: $noexport $export; subshell=subshell); bash -c 'echo subprocess: $noexport $export; subprocess=subprocess'; echo parent: $subshell $subprocess
subshell: noexport export
subprocess: export
parent:
Il existe encore une source de confusion: certains pensent que les sous-processus "fourchus" sont ceux qui ne voient pas les variables non exportées. Habituellement, fork () s sont immédiatement suivis par exec () s, et c’est pourquoi il semblerait que fork () soit ce qu’il faut rechercher, alors qu’il s’agit en fait de exec (). Vous pouvez exécuter des commandes sans fork () avant avec la commande exec
, et les processus lancés par cette méthode n'auront également pas accès aux variables non exportées:
$ noexport=noexport; export export=export; exec bash -c 'echo execd process: $noexport $export; execd=execd'; echo parent: $execd
execd process: export
Notez que nous ne voyons pas la ligne parent:
, car nous avons remplacé le shell parent par la commande exec
. Il ne reste donc plus rien pour exécuter cette commande.
export NAME=value
pour les paramètres et les variables qui ont une signification pour un sous-processus.
NAME=value
pour les variables temporaires ou de boucle privées du processus Shell en cours.
Plus en détail, export
marque le nom de la variable dans l'environnement qui copie dans un sous-processus et ses sous-processus lors de la création. Aucun nom ou valeur n'est jamais copié à partir du sous-processus.
Une erreur courante consiste à placer un espace autour du signe égal:
$ export FOO = "bar"
bash: export: `=': not a valid identifier
Seule la variable exportée (B
) est vue par le sous-processus:
$ A="Alice"; export B="Bob"; echo "echo A is \$A. B is \$B" | bash
A is . B is Bob
Les modifications apportées au sous-processus ne modifient pas le shell principal:
$ export B="Bob"; echo 'B="Banana"' | bash; echo $B
Bob
Les valeurs marquées pour l'exportation ont des valeurs copiées lors de la création du sous-processus:
$ export B="Bob"; echo '(sleep 30; echo "Subprocess 1 has B=$B")' | bash &
[1] 3306
$ B="Banana"; echo '(sleep 30; echo "Subprocess 2 has B=$B")' | bash
Subprocess 1 has B=Bob
Subprocess 2 has B=Banana
[1]+ Done echo '(sleep 30; echo "Subprocess 1 has B=$B")' | bash
Seules les variables exportées font partie de l'environnement (man environ
):
$ ALICE="Alice"; export BOB="Bob"; env | grep "ALICE\|BOB"
BOB=Bob
Donc, maintenant il devrait être aussi clair que l'est le soleil de l'été! Merci à Brain Agnew, alexp et William Prusell.
export
rendra la variable disponible pour tous les shells dérivés du shell actuel.
Il est à noter que vous pouvez exporter une variable et modifier ultérieurement la valeur. La valeur modifiée de la variable sera disponible pour les processus enfants. Une fois que l'exportation a été définie pour une variable, vous devez utiliser export -n <var>
pour supprimer la propriété.
$ K=1
$ export K
$ K=2
$ bash -c 'echo ${K-unset}'
2
$ export -n K
$ bash -c 'echo ${K-unset}'
unset
Comme vous le savez peut-être déjà, UNIX permet aux processus d’avoir un ensemble de variables d’environnement, qui sont des paires clé/valeur, les clés et les valeurs étant des chaînes. Le système d'exploitation est responsable de la conservation de ces paires pour chaque processus séparément.
Le programme peut accéder à ses variables d'environnement via cette API UNIX:
char *getenv(const char *name);
int setenv(const char *name, const char *value, int override);
int unsetenv(const char *name);
Les processus héritent également des variables d'environnement des processus parents. Le système d'exploitation est responsable de la création d'une copie de tous les "envars" au moment de la création du processus enfant.
Bash , entre autres shells, est capable de définir ses variables d'environnement à la demande de l'utilisateur. C’est pour cela que export
existe.
export
est une commande Bash permettant de définir une variable d'environnement pour Bash. Toutes les variables définies avec cette commande seraient héritées par tous les processus que ce Bash créerait.
Plus sur Environment in Bash
Un autre type de variable dans Bash est la variable interne. Puisque Bash n’est pas simplement un shell interactif, c’est en fait un interpréteur de script. Comme tout autre interpréteur (par exemple, Python), il est capable de conserver son propre ensemble de variables. Il convient de mentionner que Bash (contrairement à Python) ne prend en charge que les variables de chaîne.
La notation pour la définition des variables Bash est name=value
. Ces variables restent dans Bash et n'ont rien à voir avec les variables d'environnement conservées par le système d'exploitation.
Plus sur Paramètres du shell (y compris les variables)
Il convient également de noter que, selon le manuel de référence de Bash:
L'environnement de toute commande ou fonction simple peut être augmenté temporairement en le préfixant avec des affectations de paramètres, comme décrit dans la section Paramètres de shell . Ces instructions d'affectation n'affectent que l'environnement vu par cette commande.
Pour résumer les choses:
export
est utilisé pour définir la variable d'environnement dans le système d'exploitation. Cette variable sera disponible pour tous les processus enfants créés par le processus Bash en cours.Le réponse acceptée implique cela, mais je voudrais expliciter la connexion aux commandes intégrées de Shell:
Comme déjà mentionné, export
mettra une variable à la disposition du shell et des enfants. Si export
est pas utilisé , la variable sera uniquement disponible dans le shell et uniquement dans le shell builtins peuvent y accéder.
C'est,
tango=3
env | grep tango # prints nothing, since env is a child process
set | grep tango # prints tango=3 - "type set" shows `set` is a Shell builtin
Voici encore un autre exemple:
VARTEST="value of VARTEST"
#export VARTEST="value of VARTEST"
Sudo env | grep -i vartest
Sudo echo ${Sudo_USER} ${Sudo_UID}:${Sudo_GID} "${VARTEST}"
Sudo bash -c 'echo ${Sudo_USER} ${Sudo_UID}:${Sudo_GID} "${VARTEST}"'
En utilisant uniquement l'exportation VARTEST, la valeur de VARTEST est disponible dans Sudo bash -c '...'!
Pour d'autres exemples, voir:
bash-hackers.org/wiki/doku.php/scripting/processtree
Deux des créateurs d'UNIX, Brian Kernighan et Rob Pike, l'expliquent dans leur livre "The UNIX Programming Environment". Google pour le titre et vous trouverez facilement une version pdf.
Ils abordent les variables Shell dans la section 3.6 et se concentrent sur l'utilisation de la commande export
à la fin de cette section:
Lorsque vous souhaitez rendre la valeur d'une variable accessible dans des sous-shells, vous devez utiliser la commande d'exportation du shell. (Vous pourriez penser à la raison pour laquelle il n’existe aucun moyen d’exporter la valeur d’une variable d’un sous-shell à son parent).
Juste pour montrer la différence entre une variable exportée se trouvant dans l'environnement (env) et une variable non exportée ne se trouvant pas dans l'environnement:
Si je fais ça:
$ MYNAME=Fred
$ export OURNAME=Jim
alors seulement $ OURNAME apparaît dans env. La variable $ MYNAME n'est pas dans env.
$ env | grep NAME
OURNAME=Jim
mais la variable $ MYNAME existe dans le shell
$ echo $MYNAME
Fred
Bien que cela ne soit pas explicitement mentionné dans la discussion, il n'est PAS nécessaire d'utiliser export pour créer un sous-shell à partir de bash car toutes les variables sont copiées dans le processus enfant.
Par défaut, les variables créées dans un script ne sont disponibles que pour le shell actuel. Les processus enfants (sous-coques) n'auront pas accès aux valeurs définies ou modifiées. Autoriser les processus enfants à voir les valeurs nécessite l'utilisation de la commande export.