Qu'est-ce qu'une variable d'environnement?

42

Je sais que cela VARIABLE=valuecrée une variable d’environnement et le export VARIABLE=valuerend disponible pour les processus créés par le shell actuel. envmontre les variables d'environnement actuelles, mais où vivent-elles? Que comprend une variable d'environnement (ou un environnement , d'ailleurs)?

Mat
la source

Réponses:

29

Un environnement n’est pas aussi magique que cela puisse paraître. Le shell le stocke en mémoire et passe à l' execve()appel système. Le processus enfant en hérite sous la forme d'un pointeur de tableau appelé environ. De la execvepage de manuel:

SYNOPSIS

   #include <unistd.h>

   int execve(const char *filename, char *const argv[],
              char *const envp[]);

argvest un tableau de chaînes d'arguments passées au nouveau programme.
Par convention, la première de ces chaînes devrait contenir le nom de fichier associé au fichier en cours d'exécution. envpest un tableau de chaînes, classiquement de la forme clé = valeur, qui sont transmises en tant qu’environnement au nouveau programme.

La environ(7)page de manuel offre également quelques informations:

SYNOPSIS

   extern char **environ;

LA DESCRIPTION

La variable environpointe vers un tableau de pointeurs vers des chaînes appelé "environnement". Le dernier pointeur de ce tableau a la valeur NULL. (Cette variable doit être déclarée dans le programme utilisateur, mais elle l'est dans le fichier d' <unistd.h>en-tête si les fichiers d'en-tête proviennent de libc4 ou de libc5 et s'ils proviennent de la glibc et que _GNU_SOURCE a été défini.) Ce tableau de chaînes est mis à disposition pour le processus par l'appel exec (3) qui a lancé le processus.

Ces deux pages de manuel GNU correspondent à la spécification POSIX.

Jordan
la source
4
+1, il est probablement intéressant de noter que certains membres de la exec(3)famille (c'est-à-dire ceux qui ne correspondent pas à exec * v) passent ** environ sous les couvertures.
msw
5
Notez qu'il ne s'agit pas de processus enfants (les processus enfants héritent de toute la mémoire de leur parent), mais de programmes exécutés (dans le même processus), c'est donc un autre moyen de transmettre des données à un appel système execve () (qui autrement efface la mémoire du processus).
Stéphane Chazelas
@msw: Ce sont les exec*evariantes qui transmettent explicitement un env, au lieu d'utiliser implicitement la environvariable globale. Le vmoyen "vecteur" et les arguments de ligne de commande passés sous forme de tableau (plutôt que de "liste" (fonction de longueur variable)) execveconstituent un appel système et toutes les autres exec*fonctions sont des wrappers libc.
Peter Cordes
19

Vous vous trompez un peu: SOME_NAME=valuecrée une variable shell (dans la plupart des shells). export SOME_NAME=valuecrée une variable d'environnement. Pour le meilleur pour le pire, la plupart des shells Unix / Linux / * BSD utilisent une syntaxe identique pour accéder aux variables d'environnement et aux variables shell.

Dans un sens plus large, un "environnement" est simplement l'information qui accompagne l'exécution du programme. Dans les programmes C, vous trouverez peut - être le processus ID avec un getpid()appel, dans un programme shell que vous utilisez un accès variable: $$. L'ID de processus fait simplement partie de l'environnement du programme. Je crois que le terme "environnement" vient de certains sujets plus théoriques de l'informatique, tels que la modélisation de l'exécution de programmes. Les modèles d'exécution de programmes ont un environnement "qui contient les associations entre les variables et leurs valeurs".

Et cette dernière définition, plus forte, est ce qu’est un "environnement" pour les shells Unix / Linux / * BSD: une association entre les noms ("variables") et leurs valeurs. Pour la plupart des shells de style Unix, les valeurs sont toutes des chaînes de caractères, bien que ce ne soit plus aussi vrai qu'avant. Ksh, Zsh et Bash ont tous des variables typées ces jours-ci. Même les définitions de fonctions de shell peuvent être exportées.

L'utilisation d'un environnement distinct des variables de shell brut implique la fork/execméthode de démarrage d'un nouveau processus utilisé par tous les systèmes Unix. Lorsque vous utilisez exportune paire nom / valeur, cette paire nom / valeur sera présente dans l'environnement des nouveaux exécutables, lancée par le shell avec un execve(2)appel système (généralement après un fork(2), sauf lorsque la execcommande shell a été utilisée).

Après un execve(), la main()fonction de nouveau binaire a ses arguments en ligne de commande, l’environnement (stockés sous forme de tableau de pointeurs vers des var=valuechaînes terminé par NULL , voir la environ(7)page de manuel). Les autres états hérités incluent les ulimitparamètres, le répertoire de travail en cours et les descripteurs de fichier ouverts pour lesquels l' execve()appelant n'a pas défini FD_CLOEXEC. L'état actuel du terminal (écho activé, mode brut, etc.) peut également être considéré comme faisant partie de l'état d'exécution hérité par un nouveau execprocessus.

Reportez-vous bashà la description de l' environnement d'exécution dans le manuel pour des commandes simples (autres que les fonctions intégrées ou shell).

L’environnement Unix est différent d’au moins certains autres systèmes d’exploitation: les processus "lexicaux" de VMS peuvent être modifiés par un processus enfant, et cette modification est visible dans le parent. Un VMS cddans un processus enfant affecterait le répertoire de travail du parent. Au moins dans certaines circonstances, et ma mémoire peut me manquer.

Certaines variables d'environnement sont bien connues, $HOME, $PATH, $LD_LIBRARY_PATHet d' autres. Certains sont conventionnels pour un système de programmation donné, de sorte qu'un shell parent peut transmettre beaucoup d'informations spécifiques à certains programmes, comme un répertoire temporaire spécifique, ou un ID utilisateur et un mot de passe qui ne s'affichent pas ps -ef. Les programmes CGI simples héritent par exemple de nombreuses informations du serveur Web via des variables d'environnement.

Bruce Ediger
la source
1
Cela semblerait être un peu plus compliqué encore. Au moins, bash SOME_NAME=value commanddéfinira la variable d'environnement SOME_NAME pour cet appel de commande. De manière confuse, cela ne semble pas définir la variable shell du même nom.
Samuel Edwin Ward
2
Pour être plus précis, les variables d'environnement ne sont pas héritées, mais plutôt explicitement passées d'un shell à des programmes générés.
msw
2
@SamuelEdwinWard si votre SOME_NAME=value commandcomportement est contraire à vos attentes, c'est qu'il s'agit d'une syntaxe spéciale signifiant "ajoutez SOME_NAME à l'environnement transmis à commande mais ne modifiez pas les variables de ce shell".
msw
1
Fascinant, le lien au lambda calcul / à la programmation fonctionnelle. C'est un lien intéressant qui a beaucoup de sens.
Matt
1
Certaines de ces choses ne sont pas tout à fait correctes. Par exemple, sous - couches sont des sous - processus et doivent être fork()ed, mais ils ne reçoivent (copies) de variables shell.
Ruakh
7

Les variables d'environnement dans leur forme la plus brute ne sont qu'un ensemble de paires nom / valeur. Comme décrit dans la page de manuel bash ( man 1 bash) de la section ENVIRONMENT:

   When  a  program  is invoked it is given an array of strings called the
   environment.   This  is  a  list  of  name-value  pairs,  of  the  form
   name=value.

   The  shell  provides  several  ways  to manipulate the environment.  On
   invocation, the shell scans its own environment and creates a parameter
   for  each name found, automatically marking it for export to child pro-
   cesses.  Executed commands inherit the  environment.

Concrètement, cela vous permet de définir un comportement partagé ou unique pour les programmes appelés à partir du shell actuel. Par exemple, lorsque vous utilisez crontabou visudovous pouvez définir la EDITORvariable d'environnement pour définir un autre éditeur que celui que votre système utiliserait par défaut. Il en va de même pour des éléments tels que la mancommande qui examine votre PAGERenvironnement pour déterminer le programme de pagination à utiliser pour afficher le résultat de la page de manuel.

Beaucoup de commandes unix lisent l'environnement et, en fonction de ce qui est défini, modifient leur sortie / traitement / action en fonction de celles-ci. Certains sont partagés, certains sont uniques au programme. La plupart des pages de manuel contiennent des informations sur l'impact de la variable d'environnement sur le programme décrit.

D'autres illustrations pratiques concernent, par exemple, les systèmes avec plusieurs installations d'Oracle sur la même plate-forme. En définissant ORACLE_HOMEl'ensemble des commandes Oracle (telles qu'elles sont chargées à partir de votre PATHvariable d'environnement), extrayez les paramètres, les définitions, les mappages et les bibliothèques de ce répertoire de niveau supérieur. Il en va de même pour d'autres programmes tels que Java avec sa JAVA_HOMEvariable d'environnement.

bash a lui-même de nombreuses variables d’environnement qui peuvent changer le comportement de plusieurs éléments: historique ( HISTSIZE, HISTFILEetc.), taille de l’écran ( COLUMNS), complétion des onglets ( FIGNORE, GLOBIGNORE) locale et codage / décodage des caractères ( LANG, LC_*), invite ( PS1.. PS4) et etc. (cherchez de nouveau la connaissance sur la page de manuel bash).

Vous pouvez également écrire des scripts / programmes qui utilisent vos propres variables d’environnement personnalisées (pour définir des paramètres ou modifier des fonctionnalités).

Drav Sloan
la source
0

Les "variables d'environnement" sont un ensemble de valeurs nommées dynamiques qui peuvent affecter le comportement des processus en cours sur un ordinateur.

Ils font partie de l'environnement d'exploitation dans lequel un processus s'exécute. Par exemple, un processus en cours d'exécution peut interroger la valeur de la variable d'environnement TEMP pour découvrir un emplacement approprié pour stocker des fichiers temporaires, ou la variable HOME ou USERPROFILE pour rechercher la structure de répertoires appartenant à l'utilisateur exécutant le processus.

Plus d'informations ici → http://en.wikipedia.org/wiki/Variable_Environment .

Tout ce que vous voulez savoir sur les variables d'environnement ... ↑

SoCalDiegoRob
la source
1
Bien qu'il soit peu probable que ces liens disparaissent, il est préférable de répondre à la question ici avec un texte pertinent et de fournir le lien en complément des informations de sauvegarde.
Anthon
@ Anthony Je pense que vous avez raison et je ferai les changements dès que je pourrai ... Merci pour le conseil ...
SoCalDiegoRob le
-1

Cette réponse nécessite une certaine expérience et une connaissance des scripts shell avec les termes variable, valeur, substitution de variable, invite, écho, noyau, shell, utilitaire, session et processus.

Une variable d'environnement (envar) est un ensemble de variables globales définies pouvant influer sur le comportement d'un processus donné sur le système d'exploitation d'un ordinateur.

1. Une introduction exemplaire:

Nous substituons envars avec un $et lettres majuscules . Par exemple: $PS1.

Nous pouvons imprimer un envar de cette façon:

echo $PS1

$PS1contient la valeur de l'invite Unix. Disons que ses valeurs natives sont \u \w $.

  • \u représente l'utilisateur (actuel),
  • \w est synonyme de répertoire de travail,
  • $ est à la frontière de l'invite.

Donc, si nous le faisons echo $PS1, nous voyons les valeurs de \u, \wplus le signe dollar à la fin.

Nous pourrions changer le comportement Unix dans ce contexte, si nous changeons les valeurs de cet environnement. Par exemple:

PS1="\w >"

Maintenant, l'invite ressemble à ceci (en supposant que le répertoire de travail s'appelle "John"):

John >

De la même manière que nous pourrions le faire PS1="Hello, I'm your prompt >", echo $PS1nous apporterons:

Hello, I'm your prompt >

Dans Bash 4.xx, nous pouvons imprimer TOUS les envars du système avec la envcommande. Je suggère d'exécuter envdans le terminal et de regarder la sortie.

2. Comment ces données sont-elles affichées et manipulées:

Le terminal d’une session permet de personnaliser les envars de Bash.

Les modifications susmentionnées sont généralement temporaires et voici pourquoi:

Chaque session (qui n'est pas une sous-session) est unique et plusieurs processus peuvent s'exécuter de manière unique en même temps (chacun avec son propre ensemble d'environs), mais il existe généralement un héritage de la session 0 à la session 1 et plus.

Les modifications que nous apportons à un processus lui sont propres et cesseront si nous le fermons sans les sauvegarder.

Alors, comment pouvons-nous enregistrer ces modifications:

Il existe plusieurs types de manières de stocker les modifications d’envar, en fonction de la portée choisie. Voici différents niveaux (niveaux) pour de tels changements:

  • Niveau de processus: les envars ne sont disponibles que pour les programmes de la session en cours.
  • Niveau d'exportation: les envars sont disponibles pour les programmes de la session en cours ou de toutes ses sous-sessions.
  • Niveau global: Les modifications seront stockées pour toutes les sessions, quelles qu'elles soient (primaire et tous les sous-marins).

Où sont les données envar stockées:

Unix est composé de 3 couches principales: le noyau, le shell et les utilitaires. Autant que je sache, chaque shell a ses propres envars, et ceux-ci sont construits principalement ou exclusivement dans le shell.

Le lieu spécifique dans lequel changer globalement ceux-ci est généralement /etc/profilebien que nous puissions également le faire dans .bashrcbien sûr.

3. Créer de nouveaux envars:

Nous pouvons créer de nouveaux envars et voici un moyen; depuis Bash 4.xx, il n’ya pas d’enavar natif nommé MESSAGE(comme indiqué, les envars sont généralement en majuscule).

MESSAGE="Hello world!"

va le créer pour nous, et maintenant si nous tapons echo $MESSAGE, nous obtenons hello world!.

Si nous exécutons bashdans notre session de travail actuelle (fenêtre), nous commencerions une nouvelle sous-session bash et ne fonctionnerons plus dans le processus d'origine, à moins que nous ne l'exécutions exit.

Remarque: Dans les systèmes d'exploitation dotés d'un émulateur de terminal (tel que le bureau Ubuntu), une sous-session s'exécute généralement sur la même fenêtre, mais une nouvelle session dans une autre fenêtre n'est pas une sous-session de celle existante (il s'agit d'un processus adjacent ). .

Remarque: N'utilisez pas de signes spéciaux dans les valeurs envar telles que! ou ils ne seront pas sauvés.

Exportation de l'environnement de la session d'origine vers toutes les sous-sessions:

Nous pouvons toujours utiliser l'environnement créé dans la première session, ainsi que dans la seconde, sans l'enregistrer dans les fichiers de configuration utilisateur ou global (voir les données suivantes). Voici comment faire cela:

Accédez à la session d'origine (que ce soit sur la fenêtre en cours ou une autre) et exécutez:

export MESSAGE

lors de l'exportation, n'utilisez pas de $signe.

Il est maintenant exporté vers toutes les sous-sessions. Si vous le faites echo $MESSAGEsur une sous-session, que ce soit de votre utilisateur ou d'un autre, il sera alors imprimé.

Notez que les variables internes du shell telles que PS1ne doivent pas être exportées, mais si vous voulez les exporter de quelque manière que ce soit et qu'elles n'apparaissent pas, ne les exécutez pas bashaprès export, mais plutôt bash –norc.

4. L'environnement $ PATH:

$PATH est l’environnement que les utilisateurs changeront généralement le plus.

Si nous echo $PATH, nous allons voir ce flux:

/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

Les valeurs imprimées de cet environnement sont séparées par des deux points (:), mais voici une manière potentiellement plus confortable (ce sont les mêmes valeurs):

/usr/local/bin
/usr/bin
/bin
/usr/local/games
/usr/games

Ce sont des répertoires à rechercher lorsque nous exécutons un utilitaire.

En exécutant, which echonous obtiendrons son emplacement - par exemple, nous pourrions voir qu'il existe dans /bin/echo.

Sur cette base, nous n’avons pas besoin de taper echo envar pour afficher les valeurs d’evnar. Nous pouvons aussi faire:

/bin/echo $ENVAR

L'environnement sera toujours exécuté, par exemple:

/bin/echo $HOME

Nous donne

/home/User || /root

Tout comme:

echo $HOME

Nous donne

/home/User || /root

Remarque: $HOMEest abrégé en ~.

Les relations system- $ PATH et une interaction possible de l'utilisateur:

Dans Bash 4.xx, lorsque nous utilisons un utilitaire sans son chemin complet, le système utilisera les 6 valeurs mentionnées ci-dessus, de l' $PATHenvironnement. Donc, il commencera /user/local/binet suivra tout son contenu à la recherche de l' echoexécutable.

Dans ce cas, il s’arrêtera à /bin/echo, dans lequel, dans ce cas, l’exécutable réside.

Par conséquent, la principale raison pour laquelle nous pourrions personnaliser l’ $PATHenvironnement est l’installation d’exécutables qui ne se trouvent sous aucune de ses valeurs natives.

Après l’installation de tels exécutables, nous devons définir leur $PATHvaleur en conséquence et nous pourrons ensuite travailler avec eux.

5. Annexe - en expansion $PATH:

Nous pouvons export $PATHfaire des sous-sessions bash (qui incluent des extensions bash telles que WP-CLI pour WordPress ou Drush pour Drupal) de cette façon:

export PATH="/home/John:$PATH"

Cela ajoutera une nouvelle valeur /home/Johnà $PATH, et juste après, il y annexera toutes les valeurs natives (juste après les deux points), qui sont stockées sous la syntaxe $PATH.

Un tel changement permanent peut être effectué dans le script correspondant, généralement sous /etc/profileet sous le nom .bashrc.

JohnDoea
la source
3
Il y a énormément d'inconvénient à cette réponse: confusion de sessions et de processus, avertissement relatif !à une valeur de variable d'environnement ne fonctionnant pas située juste au-dessous d'un exemple indiquant qu'il fonctionne, fausse notion de sous-sessions, conseil plutôt bizarre sur la procédure à suivre après l'exportation d'une variable shell et une fausse notion de variables d'environnement globales.
JdeBP
warning about ! in an environment variable value not working that is right below an example showing it working? S'il vous plaît exemple.
JohnDoea
quite bizarre advice about what to do after exporting a shell variable, Que veux-tu dire exactement?
JohnDoea
false notion of global environment variables, Que veux-tu dire exactement?
JohnDoea