Linux / Commande env : transmettre un environnement à un programme
env NOM=valeur programme exécute un programme avec un environnement ajusté, sans changer les variables du shell qui l’a lancé. Avec GNU env, vous pouvez aussi retirer une variable avec -u, ignorer l’environnement hérité avec -i ou choisir un répertoire de travail avec -C.
Comprendre les arguments et les prérequis
Un programme reçoit un ensemble de variables d’environnement au moment de son lancement. env part de l’environnement qui lui est transmis, lui applique les modifications demandées, puis lance le programme. Ces changements ne remontent pas dans le shell parent.
La syntaxe générale suivante est une notation documentaire :
env [options] [NOM=valeur ...] [programme [arguments ...]]
Placez les options avant les affectations, puis le programme et ses arguments. N’ajoutez pas d’espace autour du signe égal ; citez une valeur contenant des espaces. Si un nom est affecté plusieurs fois, la dernière affectation l’emporte.
Les exemples utilisent Bash et GNU Coreutils. Vérifiez votre version et les chemins des outils :
env --version
env --help
type -P env
type -P printenv
Les options GNU telles que -C et -S ne sont pas disponibles partout. Sans programme à lancer, env affiche l’environnement obtenu ; pour lire seulement une valeur, préférez printenv NOM. Un affichage global peut contenir des jetons et autres données privées : ne le publiez pas tel quel dans un diagnostic.
Transmettre une valeur à un programme et vérifier le parent
Créez un nouveau fichier voir-env-demo.sh avec ce programme complet. Il distingue une variable absente d’une variable définie, même vide :
#!/usr/bin/env bash
if [ "${DEMO_MODE+x}" = x ]; then
printf 'DEMO_MODE défini : <%s>\n' "$DEMO_MODE"
else
printf '%s\n' 'DEMO_MODE absent'
fi
Exécutez ce bloc dans Bash :
(
export DEMO_MODE=parent
env DEMO_MODE=enfant bash voir-env-demo.sh
printf 'Valeur du parent : %s\n' "$DEMO_MODE"
)
Les lignes attendues sont :
DEMO_MODE défini : <enfant>
Valeur du parent : parent
Le Bash qui exécute le fichier reçoit la valeur enfant, tandis que le sous-shell de l’exercice garde parent. Les parenthèses évitent de modifier durablement une éventuelle variable homonyme de votre session.
Pour un programme externe, une affectation placée directement avant la commande remplit souvent le même besoin simple :
DEMO_MODE=essai bash voir-env-demo.sh
env DEMO_MODE=essai bash voir-env-demo.sh
Cette comparaison ne rend pas tous les contextes identiques : les affectations devant certaines commandes internes du shell ont leurs propres règles. env lance un programme, pas directement une fonction locale ou une commande interne telle que cd. Le guide de command explique comment le shell choisit ses fonctions et commandes internes.
Éviter une expansion trop précoce et choisir la locale
Le shell traite les guillemets et développe des variables avant de lancer env. Dans une écriture telle que env DEMO_MODE=enfant printf '%s\n' "$DEMO_MODE", la dernière référence provient donc du shell parent, pas du nouvel environnement du programme.
Si un shell enfant doit lire sa propre variable, passez-lui un code qui n’a pas déjà été développé par le parent :
env DEMO_MODE='mode test' bash -c 'printf "%s\n" "$DEMO_MODE"'
Le résultat attendu est mode test. Les apostrophes autour du code retardent ici l’expansion jusqu’au Bash enfant. Pour une logique plus longue, le fichier de démonstration reste plus lisible qu’un assemblage complexe de citations.
Pour une opération sensible à la locale, utilisez la variable appropriée. Cet exemple de tri ASCII force la locale C pour le seul programme sort :
printf 'z\nA\na\n' | env LC_ALL=C sort
Les lignes attendues sont A, a et z. LANG sert de valeur par défaut, alors qu’une valeur non vide de LC_ALL l’emporte sur les catégories de locale et sur LANG. Les définitions POSIX des variables d’environnement précisent cette priorité.
Retirer une variable ou partir d’un environnement réduit
Une valeur vide n’est pas une variable absente
env DEMO_MODE= bash voir-env-demo.sh
env -u DEMO_MODE bash voir-env-demo.sh
Dans un environnement de démonstration sans configuration enfant qui recrée cette variable, le premier appel affiche DEMO_MODE défini : <> et le second DEMO_MODE absent. Un programme peut volontairement traiter ces deux situations différemment.
-u NOM, ou --unset=NOM, retire le nom de l’environnement transmis ; il ne lance pas unset dans le shell parent. Une affectation fournie ensuite peut réintroduire le nom. Les fichiers de démarrage ou la logique du programme enfant peuvent également modifier son environnement après son lancement.
Définir explicitement ce que l’on veut conserver avec -i
-i, ou --ignore-environment, ignore l’environnement hérité. Pour observer un environnement limité à une variable de test, avec les outils installés aux chemins indiqués :
env -i DEMO_MODE=essai /usr/bin/printenv
Dans un environnement Linux ordinaire, cette commande affiche DEMO_MODE=essai. Le chemin absolu évite de dépendre d’un PATH hérité. Sans PATH, le comportement de recherche peut utiliser des valeurs par défaut propres au système : ne supposez pas une règle universelle d’absence totale de recherche.
Pour lancer un programme qui doit lui-même trouver d’autres outils, ajoutez le chemin nécessaire et la locale, en adaptant les répertoires à votre système :
env -i PATH=/usr/bin:/bin LC_ALL=C DEMO_MODE=essai bash voir-env-demo.sh
L’environnement réduit peut changer la recherche des certificats, les chemins de configuration ou les réglages de proxy. Réintroduisez uniquement les valeurs nécessaires au test. Une nouvelle instance de shell peut aussi créer des variables par défaut ; cela ne signifie pas que env -i a conservé tout l’environnement d’origine.
-i ne constitue pas une isolation des fichiers, des permissions ou du réseau. Il sert à contrôler les variables transmises et à révéler des dépendances à celles-ci, pas à modifier ces autres ressources.
Choisir le répertoire de travail avec -C
pwd
env -C /tmp pwd
pwd
Avec GNU env et un /tmp accessible, le deuxième appel demande au programme pwd d’observer ce répertoire. Les premier et troisième appels doivent retrouver le répertoire du shell parent. Cette opération ne crée pas de fichier et ne change pas le répertoire courant de votre session.
-C répertoire, ou --chdir=répertoire, change le contexte avant l’exécution. Un chemin de programme comme ./outil est donc relatif au nouveau répertoire. Si le changement de répertoire échoue, le programme demandé n’est pas lancé.
| Option GNU | Usage |
|---|---|
-i |
Ignorer l’environnement hérité avant d’appliquer les affectations. |
-u NOM |
Retirer une variable de l’environnement transmis. |
-C répertoire |
Changer le répertoire de travail avant de lancer le programme. |
-S chaîne |
Découper une chaîne en arguments, notamment pour une ligne d’interpréteur. |
-0 |
Lors de l’affichage sans programme, séparer les entrées par l’octet NUL plutôt qu’un saut de ligne. |
Le format visuel de l’environnement peut varier avec la version et ses réglages de citation. -0 fournit des séparateurs adaptés à un traitement par enregistrements, y compris quand une valeur contient un saut de ligne. Ne traitez pas une copie quelconque d’un affichage comme un fichier de commandes à exécuter.
Utiliser env dans la première ligne d’un script
Une ligne d’interpréteur, ou shebang, commence par #!. La forme #!/usr/bin/env bash demande de chercher Bash selon PATH, au lieu d’imposer le chemin de son exécutable. Elle suppose toutefois que /usr/bin/env existe à cet emplacement et que le programme trouvé soit celui attendu.
Sur Linux, une ligne telle que #!/usr/bin/env bash -u ne constitue pas une manière fiable de transmettre deux arguments : le texte suivant le chemin d’interpréteur est traité comme un seul argument. Lorsque env prend en charge -S, il peut effectuer ce découpage.
Créez un nouveau fichier env-script-demo.sh avec ce contenu complet :
#!/usr/bin/env -S bash -u
printf 'Mode : %s\n' "${DEMO_MODE:-non défini}"
Dans un environnement Linux compatible, rendez uniquement ce fichier exécutable et lancez-le :
chmod u+x env-script-demo.sh
./env-script-demo.sh
Le script utilise bash -u, qui signale normalement les variables non définies ; la forme ${DEMO_MODE:-non défini} fournit ici une valeur de repli. Sans valeur non vide pour cette variable, la ligne attendue est Mode : non défini.
Pour contrôler le découpage sur une ligne de commande, passez la chaîne entre apostrophes :
env -S 'bash -u' env-script-demo.sh
-S suit ses propres règles de citation et de substitution, sans devenir un shell général. Pour un service qui doit utiliser un interpréteur déterminé, un chemin explicitement choisi peut être plus approprié qu’une recherche variable dans PATH. Le manuel officiel de GNU env décrit les options, la ligne d’interpréteur et le découpage.
Distinguer export, env et printenv, puis vérifier les erreurs
Une variable créée dans le shell n’est pas automatiquement transmise à un programme. Ce bloc de démonstration est limité à un sous-shell :
(
unset DEMO_LOCAL
DEMO_LOCAL=interne
printenv DEMO_LOCAL
printf 'Statut avant export : %s\n' "$?"
export DEMO_LOCAL
printenv DEMO_LOCAL
)
La première recherche ne produit normalement pas de valeur et renvoie 1. Après export, printenv affiche interne. env travaille sur l’environnement qui lui est transmis, pas sur l’ensemble des variables locales du shell.
| Outil ou forme | Rôle |
|---|---|
export NOM=valeur |
Marquer une variable du shell courant pour la transmettre aux programmes lancés ensuite. |
env NOM=valeur programme |
Ajuster l’environnement de ce lancement, sans modifier le shell parent. |
printenv NOM |
Lire une valeur reçue dans l’environnement, sans la modifier. |
Si un programme est introuvable, vérifiez le PATH qui lui est fourni et le répertoire choisi avec -C. Si une variable paraît inchangée, cherchez une expansion trop précoce dans le parent ou une réaffectation par le programme enfant.
GNU env renvoie 125 pour un échec propre à env, 126 si le programme est trouvé mais ne peut pas être invoqué et 127 s’il est introuvable. Sinon, il transmet le statut du programme. Vérifiez ce statut, les diagnostics et les valeurs de test nécessaires, plutôt que publier tout l’environnement pour comprendre une erreur.




