En quelque sorte une question secondaire, mais comment appelle-t-on la fonctionnalité elle-même lorsque vous définissez une variable d'environnement pour une seule sous-commande comme celle-ci? J'ai toujours eu du mal à trouver des informations à ce sujet parce que je ne sais pas comment ça s'appelle.
John Cromartie
1
@ JohnCromartie, vous devriez poser cette question sous forme de question.
@JohnCromartie C'est un composant optionnel de chaque commande shell, il se trouve donc dans la section "Commandes simples" de la plupart des manuels shell. Pour POSIX, ce serait ici . glenn a déjà lié pour vous la section analogue du manuel bash.
jw013
Définir une variable qui n'existe pas via une affectation crée une variable shell. Le paramétrage via ENV ou l'exportation de la variable la pousse dans l'environnement d'exécution du shell. La modification de la valeur d'une variable existante met à jour la valeur de l'environnement d'exécution, le cas échéant, sinon changez-la dans les variables internes du shell.
Johan
Réponses:
26
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.
Vous pouvez le faire FOO=bar exec baz, alors vous n’avez pas besoin envde votre dernier point.
Stéphane Chazelas
Lorsque vous executilisez quelque chose, utilise-t-il votre environnement actuel?
Glenn Jackman
1
Idem @StephaneChazelas, et vous pouvez également sudo FOO=bar bazpasser des variables d'environnement sans avoir besoin de env.
Mike Miller
1
@ StephaneChazelas qui ne fonctionne que si je veux mettre 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.
Patrick
@glennjackman oui, tant que les variables sont exportées ou passées avant le exec, tel que FOO=bar exec baz.
Patrick
14
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
Quand j’utilisais tcshj’écrivais (setenv FOO bar; baz)pour obtenir la fonction équivalente.
Barmar
6
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:
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.
Réponses:
Ils sont fonctionnellement équivalents.
La principale différence est qu’il
env FOO=bar baz
s’agit d’invoquer un processus intermédiaire entre le shell etbaz
, comme avecFOO=bar baz
le shell, directementbaz
.Donc, à cet égard,
FOO=bar baz
est préféré.Les seules situations où je me trouve à utiliser
env FOO=bar
sont 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
exec
la commande qui lui a été transmise, telle que:Si vous l'exécutez en tant que
myscript FOO=bar baz
,exec
cela générera une erreur car elleexec FOO=bar baz
n'est pas valide.Au lieu de cela, vous l'appelez en tant que
myscript env FOO=bar baz
qui est exécuté en tant queexec env FOO=bar baz
, et est parfaitement valide.la source
FOO=bar exec baz
, alors vous n’avez pas besoinenv
de votre dernier point.exec
utilisez quelque chose, utilise-t-il votre environnement actuel?sudo FOO=bar baz
passer des variables d'environnement sans avoir besoin deenv
.FOO=bar
dans le script. Si ceFOO
n'est pas toujours le casbar
, je ne veux pas le coder en dur, mais plutôt le transmettre.exec
, tel queFOO=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
baz
s'agisse d'un exécutable et non d'un shell intégré.Si votre shell n’est pas compatible POSIX, par exemple
csh
outcsh
, la syntaxene fonctionne pas et il n’existe pas de syntaxe de shell équivalente. Pour ces shells, la
env
commande est le seul moyen de remplacer ou d’injecter des variables d’environnement pour une seule commande.Si
baz
est un shell intégré, disonsfc
par exemple, alorsenv
ne donnera pas les mêmes résultats, carenv
exécute un nouveau processus au lieu d'être exécuté directement par le shell de commande. De plus, il n'y a pasfc
exé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 leenv
sera jamais travailler avec un builtin commefc
.En outre,
env
offre l'-i
option qui vous permet de démarrer une commande dans un environnement vide avec uniquement un ensemble spécifié de variables d'environnement. Celaenv
peut donc être très utile pour démarrer des processus dans des environnements désinfectés, par exemplela source
tcsh
j’écrivais(setenv FOO bar; baz)
pour obtenir la fonction équivalente.En plus de ce qui a déjà été dit
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:
Ou
bash
ne vous permet pas de faire:Alors que vous pouvez faire:
(pas que vous voulez ou devriez vouloir le faire). Ou:
(J'ai parfois besoin de faire ça).
Notez que
env
vous 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).la source
Une utilisation de
env
est de permettre la$PATH
recherche des exécutables dans les lignes shebang (carenv
considère$PATH
lors 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,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/perl
dans/usr/local/bin/perl
ou à 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.la source
Une autre fois où il
env
est 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 utilisantenv
à la fin d'un script qui définit un ensemble de variables sur les valeurs correctes:L'
-i
option zappe l'environnement existant. LesVAR=value
options 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 passerINFORMIXSQLHOSTS="$IXH"
àenv
if si elle$IXH
est définie sur une valeur non vide.la source