Quelle est la différence entre la commande
$ env FOO=bar baz
et
$ FOO=bar baz
Quel effet enva?
Quelle est la différence entre la commande
$ env FOO=bar baz
et
$ FOO=bar baz
Quel effet enva?
Réponses:
Ils sont fonctionnellement équivalents.
La principale différence est qu’il env FOO=bar bazs’agit d’invoquer un processus intermédiaire entre le shell et baz, comme avec FOO=bar bazle shell, directement baz.
Donc, à cet égard, FOO=bar bazest préféré.
Les seules situations où je me trouve à utiliser env FOO=barsont celles où je dois passer une commande à une autre.
Comme exemple spécifique, disons que j'ai un script d'encapsuleur qui effectue certaines modifications de l'environnement, puis appelle execla commande qui lui a été transmise, telle que:
#!/bin/bash
FOO=bob
some stuff
exec "$@"
Si vous l'exécutez en tant que myscript FOO=bar baz, execcela générera une erreur car elle exec FOO=bar bazn'est pas valide.
Au lieu de cela, vous l'appelez en tant que myscript env FOO=bar bazqui est exécuté en tant que exec env FOO=bar baz, et est parfaitement valide.
FOO=bar exec baz, alors vous n’avez pas besoin envde votre dernier point.
executilisez quelque chose, utilise-t-il votre environnement actuel?
sudo FOO=bar bazpasser des variables d'environnement sans avoir besoin de env.
FOO=bardans le script. Si ce FOOn'est pas toujours le cas bar, je ne veux pas le coder en dur, mais plutôt le transmettre.
exec, tel que FOO=bar exec baz.
Dans cet exemple particulier, il n'y a pas de différence réelle, en supposant que votre shell est un shell compatible POSIX, et en supposant qu'il bazs'agisse d'un exécutable et non d'un shell intégré.
Si votre shell n’est pas compatible POSIX, par exemple cshou tcsh, la syntaxe
FOO=bar baz
ne fonctionne pas et il n’existe pas de syntaxe de shell équivalente. Pour ces shells, la envcommande est le seul moyen de remplacer ou d’injecter des variables d’environnement pour une seule commande.
Si bazest un shell intégré, disons fcpar exemple, alors envne donnera pas les mêmes résultats, car envexécute un nouveau processus au lieu d'être exécuté directement par le shell de commande. De plus, il n'y a pas fcexécutable, il ne peut être exécuté comme une commande du shell en raison de la façon dont elle interagit avec l'environnement shell, et ainsi le envsera jamais travailler avec un builtin comme fc.
En outre, envoffre l' -ioption qui vous permet de démarrer une commande dans un environnement vide avec uniquement un ensemble spécifié de variables d'environnement. Cela envpeut donc être très utile pour démarrer des processus dans des environnements désinfectés, par exemple
env -i HOME=/tmp/homedir "PATH=`getconf PATH`" "TERM=$TERM" FOO=bar baz
tcshj’écrivais (setenv FOO bar; baz)pour obtenir la fonction équivalente.
En plus de ce qui a déjà été dit
VAR=value cmd args > redirs
En tant que fonctionnalité shell (Bourne / POSIX), le nom des variables d’environnement que vous transmettez est limité cmd. Ils doivent être des noms de variables shell valides et ne doivent pas être des variables en lecture seule ou spéciales du shell.
Par exemple, vous ne pouvez pas faire:
1=foo cmd
Ou
+++=bar cmd
bash ne vous permet pas de faire:
SHELLOPTS=xtrace cmd
Alors que vous pouvez faire:
env 1=foo cmd
env +++=bar cmd
env '=baz' cmd
(pas que vous voulez ou devriez vouloir le faire). Ou:
env SHELLOPTS=xtrace cmd
(J'ai parfois besoin de faire ça).
Notez que envvous ne pouvez toujours pas transmettre une chaîne de variable d'environnement qui ne contient pas de =(non que vous ne souhaitiez pas le faire non plus).
Une utilisation de envest de permettre la $PATHrecherche des exécutables dans les lignes shebang (car envconsidère $PATHlors de la recherche de l'exécutable). Ceci est utile si l'exécutable que vous voulez appeler peut se trouver à différents endroits sur différentes machines. Par exemple,
#!/usr/bin/env perl
dans la première ligne d'un script avec un bit exécutable, ce script sera exécuté avec Perl, qu'il soit installé dans, /usr/bin/perldans /usr/local/bin/perlou à un endroit complètement différent, tant que le répertoire est dans le chemin.
Bien sûr, cette recherche de chemin comporte un risque supplémentaire, mais le risque n’est pas plus grand que si vous aviez écrit explicitement perl yourscript.pl, ce qui permet également de rechercher perl dans le chemin de recherche.
Une autre fois où il envest vraiment utile est de contrôler totalement l’environnement. Je lance un programme serveur (Informix, au cas où vous ne pourriez pas deviner) dont je veux contrôler complètement l’environnement. Je l'exécute en utilisant envà la fin d'un script qui définit un ensemble de variables sur les valeurs correctes:
env -i HOME="$IXD" \
INFORMIXDIR="$IXD" \
INFORMIXSERVER="$IXS" \
${IXC:+INFORMIXCONCSMCFG="$IXC"} \
${IXH:+INFORMIXSQLHOSTS="$IXH"} \
IFX_LISTEN_TIMEOUT=3 \
ONCONFIG="onconfig.$IXS" \
PATH="/bin:/usr/bin:$IXD/bin" \
SHELL=/bin/ksh \
TZ=UTC0 \
$ONINIT "$@"
L' -ioption zappe l'environnement existant. Les VAR=valueoptions suivantes définissent les variables d’environnement que je souhaite définir; le nom du programme est dedans $ONINIT, et tous les arguments de ligne de commande sont passés verbatim avec "$@".
La ${IXH:+INFORMIXSQLHOSTS="$IXH"}construction ne fait que passer INFORMIXSQLHOSTS="$IXH"à envif si elle $IXHest définie sur une valeur non vide.