Question Quelle est la différence entre set, export et env et quand dois-je utiliser chacun?


De temps en temps, je bouscule un script bash et il me semble qu'il y a plusieurs manières de définir une variable:

key=value
env key=value
export key=value

Lorsque vous êtes dans un script ou une commande unique (par exemple, je mets souvent une variable avec un lanceur Wine pour définir le bon préfixe Wine), cela semble être complètement interchangeable, mais ce n'est sûrement pas le cas.

Quelle est la différence entre ces trois méthodes et pouvez-vous me donner un exemple de quand je voudrais spécifiquement les utiliser?

Relativement lié à Quelle est la différence entre `VAR = ...` et `export VAR = ...`? mais je veux savoir comment env s'inscrit dans cela aussi, et quelques exemples montrant les avantages de chacun seraient bien aussi :)


92
2017-10-24 09:34


origine


Notez que export key=value est une syntaxe étendue et ne doit pas être utilisée dans les scripts portables (c.-à-d. #! /bin/sh). - Simon Richter


Réponses:


Considérons un exemple spécifique. le grep commande utilise une variable d'environnement appelée GREP_OPTIONS pour définir les options par défaut.

À présent. Étant donné que le dossier test.txt contient les lignes suivantes:

line one
line two

exécuter la commande grep one test.txt reviendra

line one

Si vous lancez grep avec le -v option, il retournera les lignes non correspondantes, donc la sortie sera

line two

Nous allons maintenant essayer de définir l'option avec une variable d'environnement.

  1. Variables d'environnement définies sans export ne sera pas hérité dans l'environnement des commandes que vous appelez.

    GREP_OPTIONS='-v'
    grep one test.txt
    

    Le résultat:

    line one
    

    De toute évidence, l'option -v n'a pas été passé à grep.

    Vous souhaitez utiliser ce formulaire lorsque vous définissez une variable uniquement pour le shell à utiliser, par exemple dans for i in * ; do vous ne voulez pas exporter $i.

  2. Cependant, la variable est transmise à l'environnement de cette ligne de commande particulière, vous pouvez donc le faire

    GREP_OPTIONS='-v' grep one test.txt
    

    qui retournera le prévu

    line two
    

    Vous utilisez ce formulaire pour modifier temporairement l'environnement de cette instance particulière du programme lancé.

  3. L'exportation d'une variable entraîne l'héritage de la variable:

    export GREP_OPTIONS='-v'
    grep one test.txt
    

    retourne maintenant

    line two
    

    C'est la manière la plus courante de définir des variables pour l'utilisation de processus lancés ultérieurement dans un shell.

  4. Tout cela a été fait en bash. export est un bash builtin; VAR=whatever est la syntaxe bash. env, d'autre part, est un programme en soi. Quand env est appelé, les choses suivantes se produisent:

    1. La commande env est exécuté comme un nouveau processus
    2. env modifie l'environnement, et
    3. appelle la commande fournie comme argument. le env processus est remplacé par le command processus.

    Exemple:

    env GREP_OPTIONS='-v' grep one test.txt
    

    Cette commande lancera deux nouveaux processus: (i) env et (ii) grep (en réalité, le second processus remplacera le premier). Du point de vue du grep processus, le résultat est exactement le même que courir

    GREP_OPTIONS='-v' grep one test.txt
    

    Cependant, vous pouvez utiliser cet idiome si vous êtes en dehors de bash ou ne souhaitez pas lancer un autre shell (par exemple, lorsque vous utilisez le exec() famille de fonctions plutôt que la system() appel).

Note complémentaire sur #!/usr/bin/env

C'est aussi pourquoi l'idiome #!/usr/bin/env interpreterest utilisé plutôt que #!/usr/bin/interpreter. env ne nécessite pas un chemin complet vers un programme, car il utilise le execvp() fonction qui recherche dans le PATH variable comme un shell fait, puis remplace  lui-même par la commande exécutée. Ainsi, il peut être utilisé pour savoir où un interpréteur (comme perl ou python) "se trouve" sur le chemin.

Cela signifie également qu'en modifiant le chemin actuel, vous pouvez influencer la variante python qui sera appelée. Cela rend les suivants possibles:

echo -e '#!/usr/bin/bash\n\necho I am an evil interpreter!' > python
chmod a+x ./python
export PATH=.
calibre

au lieu de lancer Calibre, il en résultera

I am an evil interpreter!

92
2017-10-24 10:21



Pourquoi GREP_OPTIONS = '- v' grep one test.txt fonctionne? J'ai pensé qu'il fallait un point-virgule après '-v' (mais je l'ai essayé et ça fonctionne en fait) - Joe
Car avec un point-virgule, il est interprété comme deux commandes bash distinctes; le premier définit la variable (sans l'exporter) et le second commence par un environnement dans lequel la variable n'est pas exportée. Sans le point-virgule, cependant, il s'agit d'une commande (grep), précédée par la définition d'un environnement local. - January
Légère correction: à l'étape 4, où vous avez env GREP_OPTIONS grep one test.txt, Je pense que ça devrait être env GREP_OPTIONS='-v' grep one test.txt - yshavit
D'où viennent toutes les variables de env viens de si? Je veux dire quand vous ouvrez un nouveau shell, vous avez toujours quelques variables. Donc, certains programmes doivent avoir exported ceux, non? - Pithikos
Les variables @Pithikos Environment sont définies en "créant un environnement". Par défaut, bash fournira un bashrc à l'échelle du système (ou profile.d ou bash_profile). Ensuite, il source votre utilisateur ~ / .bashrc (et / ou ~ / .bash_profile). Chacun de ces fichiers peut contenir des commandes bash pour obtenir d'autres scripts, vous pouvez donc avoir des variables d'environnement provenant de partout. - Eric