web-dev-qa-db-fra.com

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

De temps en temps, je rédige un script bash et il me semble qu'il existe plusieurs façons de définir une variable:

key=value
env key=value
export key=value

Lorsque vous êtes dans un script ou une seule commande (par exemple, je vais souvent chaîner une variable avec un lanceur Wine pour définir le préfixe Wine correct), celles-ci semblent être complètement interchangeables, mais ce ne peut certainement pas être le cas.

Quelle est la différence entre ces trois méthodes et pouvez-vous me donner un exemple du moment où je souhaiterais spécifiquement utiliser chacune d'elles?

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

110
Oli

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

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

line one
line two

l'exécution de la commande grep one test.txt retournera

line one

Si vous exécutez grep avec l’option -v, les lignes qui ne correspondent pas seront renvoyées, ainsi le résultat sera

line two

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

  1. Les variables d'environnement définies sans export ne seront pas héritées de 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é transmise à grep.

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

  2. Cependant, la variable est transmise à l'environnement de cette ligne de commande, vous pouvez donc effectuer

    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
    

    revient maintenant

    line two
    

    C'est le moyen le plus courant de définir des variables pour l'utilisation de processus démarrés ultérieurement dans un shell

  4. Tout a été fait à Bash. export est une bash intégrée; VAR=whatever est la syntaxe bash. env, d'autre part, est un programme en soi. Lorsque env est appelé, les événements suivants se produisent:

    1. La commande env est exécutée en tant que nouveau processus.
    2. env modifie l'environnement, et
    3. appelle la commande fournie en argument. Le processus env est remplacé par le processus command.

    Exemple:

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

    Cette commande lancera deux nouveaux processus: (i) env et (ii) grep (en réalité, le deuxième processus remplacera le premier). Du point de vue du processus grep, le résultat est exactement identique à l'exécution

    GREP_OPTIONS='-v' grep one test.txt
    

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

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

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

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

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!
109
January