À quoi ça sert export
?
Quelle est la différence entre:
export name=value
et
name=value
À quoi ça sert export
?
Quelle est la différence entre:
export name=value
et
name=value
Réponses:
export
met la variable à la disposition des sous-processus.
C'est,
export name=value
signifie que le nom de la variable est disponible pour tout processus que 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 variable est limitée au shell et n'est disponible pour aucun autre processus. Vous l'utiliseriez pour (par exemple) les variables de boucle, les variables temporaires, etc.
Il est important de noter que l'exportation d'une variable ne la rend pas disponible pour les processus parents. En d'autres termes, la spécification et l'exportation d'une variable dans un processus généré ne la rend pas disponible dans le processus qui l'a lancée.
name=value command
ne faire la variable disponible dans le sous-processus command
.
D'autres ont répondu que l'exportation rend la variable disponible pour les sous-coquilles, et c'est correct mais simplement un effet secondaire. Lorsque vous exportez une variable, elle place cette variable dans l'environnement du shell actuel (c'est-à-dire que 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-coquilles.
Edit (avec une perspective de 5 ans): c'est une réponse idiote. Le but de l '«exportation» est de faire en sorte que les variables «soient dans l'environnement des commandes exécutées ultérieurement», que ces commandes soient des sous-coquilles ou des sous-processus. Une implémentation naïve serait de simplement mettre la variable dans l'environnement du shell, mais cela rendrait l'implémentation impossible export -p
.
bash
, l'exportation ajoute en effet la variable à l'environnement du shell courant, mais ce n'est pas le cas avec dash
. Il me semble que l'ajout de la variable à l'environnement du shell actuel est le moyen le plus simple d'implémenter la sémantique de export
, mais ce comportement n'est pas obligatoire.
dash
a à voir. L'affiche originale posait une question spécifique bash
.
bash
mais s'applique également à toute variante de bourne-shell. Être trop précis et fournir des réponses qui ne s'appliquent qu'à bash
est un grand mal.
bash
est la jQuery du shell.
export makes the variable available to subshells, and that is correct
Il s'agit d'une utilisation très déroutante de la terminologie. Les sous-coquilles n'ont pas besoin export
d'hériter de variables. Les sous-processus le font.
Il a été dit qu'il n'est pas nécessaire d'exporter en bash lors de la ponte des sous-coquilles, tandis que d'autres ont dit exactement le contraire. Il est important de noter la différence entre les sous - shells (ceux qui sont créés par ()
, ``
, $()
ou boucles) et des sous - processus (processus qui sont invoqués par nom, par exemple un littéral bash
apparaissant dans votre script).
Ce qui est courant dans ces deux constructions, c'est que ni l'une ni l'autre ne peut retransmettre des 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 une autre source de confusion: certains pensent que les sous-processus «fourchus» sont ceux qui ne voient pas les variables non exportées. En général, les fork () sont immédiatement suivis des exec (), et c'est pourquoi il semblerait que le fork () soit la chose à rechercher, alors qu'en fait c'est le exec (). Vous pouvez exécuter des commandes sans fork () en premier avec la exec
commande, et les processus démarrés par cette méthode n'auront pas non plus 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 parent:
ligne cette fois, car nous avons remplacé le shell parent par la exec
commande, il ne reste donc plus rien pour exécuter cette commande.
&
) crée également un sous-shell.
var=asdf bash -c 'echo $var'
ou var=asdf exec bash -c 'echo $var'
? La sortie est asdf
. Le ;
fait la différence s'il est placé après la définition de la variable. Quelle serait l'explication? Il ressemble en quelque sorte var
(sans ;
) au sous-processus généré, car le shell d'origine n'a rien à voir avec cela. echo $var
n'imprime rien s'il est exécuté sur la deuxième ligne. Mais une ligne var=asdf bash -c 'echo $var'; echo $var
donne asdf\nasdf
.
export NAME=value
pour les paramètres et les variables qui ont un sens 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 recopié à 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 du sous-processus ne modifient pas le shell principal:
$ export B="Bob"; echo 'B="Banana"' | bash; echo $B
Bob
Les variables 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
Alors maintenant, il devrait être aussi clair que le soleil de l'été! Merci à Brain Agnew, alexp et William Prusell.
Il convient de 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 faire 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, la clé et la valeur étant des chaînes. Le système d'exploitation est chargé de conserver 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 où le processus enfant est créé.
Bash , entre autres shells, est capable de définir ses variables d'environnement à la demande de l'utilisateur. C'est export
pour ça.
export
est une commande Bash pour définir la 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.
En savoir plus sur l' environnement à Bash
Un autre type de variable dans Bash est la variable interne. Puisque Bash n'est pas seulement 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.
En savoir plus sur les 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 temporairement augmenté en le préfixant avec des affectations de paramètres, comme décrit dans Paramètres du shell . Ces instructions d'affectation affectent uniquement l'environnement vu par cette commande.
Pour résumer:
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 actuel pour toujours.La réponse acceptée implique cela, mais je voudrais rendre explicite la connexion aux commandes internes du shell:
Comme déjà mentionné, export
rendra une variable disponible à la fois pour le shell et les enfants. Si export
n'est pas utilisé, la variable ne sera disponible que dans le shell, et seules les commandes internes du shell pourront 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}"'
Ce n'est qu'en utilisant l'exportation VARTEST que 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 traitent des variables shell dans la section 3.6, et se concentrent sur l'utilisation de la export
commande à la fin de cette section:
Lorsque vous souhaitez rendre la valeur d'une variable accessible dans des sous-shells, la commande d'exportation du shell doit être utilisée. (Vous pourriez penser à pourquoi il n'y a aucun moyen d'exporter la valeur d'une variable d'un sous-shell vers 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 l'env. La variable $ MYNAME n'est pas dans l'env.
$ env | grep NAME
OURNAME=Jim
mais la variable $ MYNAME existe dans le shell
$ echo $MYNAME
Fred
Par défaut, les variables créées dans un script ne sont disponibles que pour le shell courant; les processus enfants (sous-shells) n'auront pas accès aux valeurs qui ont été définies ou modifiées. Pour permettre aux processus enfants de voir les valeurs, vous devez utiliser la commande d'exportation.
Bien que cela ne soit pas explicitement mentionné dans la discussion, il n'est PAS nécessaire d'utiliser l'export lors de la génération d'un sous-shell depuis bash puisque toutes les variables sont copiées dans le processus enfant.
export name=value
n'est pas portable. Selon ce que vous voulez exactement, essayezname=value; export name
une solution portable.