J'ai lu ici que le but de export
dans un shell est de rendre la variable disponible aux sous-processus lancés depuis le 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 d'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 ?
Réponse acceptée :
Votre hypothèse est que les variables shell sont dans l'environnement . Ceci est une erreur. Le export
La commande est ce qui définit un nom comme étant dans l'environnement. Ainsi :
a=1 b=2
export b
résultats dans le shell actuel sachant que $a
se développe en 1 et $b
à 2, mais les sous-processus ne sauront rien de a
car il ne fait pas partie de l'environnement (même dans le shell actuel).
Quelques outils utiles :
set
:Utile pour afficher les paramètres du shell actuel, exportés ou nonset -k
:Définit les arguments assignés dans l'environnement. Considérezf() { set -k; env; }; f a=1
set -a
:indique au shell de mettre n'importe quel nom défini dans l'environnement. Comme mettreexport
avant chaque mission. Utile pour.env
fichiers, comme dansset -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 parler des hérités environnement, il est donc utile pour vérifier l'intégrité.env -i
:Utile pour nettoyer l'environnement avant de démarrer un sous-processus.
Alternatives à export
:
name=val command
# L'affectation avant la commande exporte ce nom vers la commande.declare/local -x name
# Exporte le nom, particulièrement utile dans les fonctions shell lorsque vous souhaitez éviter d'exposer le nom à une portée extérieure.set -a
# Exporte chaque devoir suivant.
Motivations
Alors pourquoi les shells ont-ils besoin d'avoir leurs propres variables et leur environnement différent ? Je suis sûr qu'il y a des raisons historiques, mais je pense que la raison principale est la portée. L'environnement est destiné aux sous-processus, mais il existe de nombreuses opérations que vous pouvez effectuer dans le shell sans créer de sous-processus. Supposons que vous bouclez :
for i in {0..50}; do
somecommand
done
Pourquoi gaspiller de la mémoire pour somecommand
en incluant i
, rendant son environnement plus grand qu'il ne devrait l'être ? Que se passe-t-il si le nom de la variable que vous avez choisi dans le shell signifie quelque chose d'involontaire pour le programme ? (Mes favoris personnels incluent DEBUG
et VERBOSE
. Ces noms sont utilisés partout et rarement dans les espaces de noms de manière adéquate.)
Qu'est-ce que l'environnement sinon le shell ?
Parfois, pour comprendre le comportement d'Unix, vous devez regarder les appels système, l'API de base pour interagir avec le noyau et le système d'exploitation. Ici, nous regardons le exec
famille d'appels, qui est ce que le shell utilise lorsqu'il crée un sous-processus. Voici une citation de la page de manuel pour exec(3)
(c'est moi qui souligne):
Le
execle()
etexecvpe()
Les fonctions permettent à l'appelant de spécifier l'environnement du programme exécuté via l'argument envp. L'argument envp est un tableau de pointeurs vers des chaînes terminées par null et doit être terminé par un pointeur NULL. Les autres fonctions prennent l'environnement de la nouvelle image de processus à partir de la variable externe environ dans le processus appelant.
Donc écrire export somename
dans le shell équivaudrait à copier le nom dans le dictionnaire global environ
en C. Mais en attribuant somename
sans l'exporter, ce serait comme l'assigner en C, sans le copier dans l'environ
variables.