Tutoriel Linux

Export sous Linux : rendre une variable disponible sans casser le shell

Débutant6 min de lecture

Vous définissez une variable dans Bash, votre commande la lit correctement, puis le script lancé juste après la voit vide. Le problème vient souvent d’une différence simple : une variable du shell courant n’est pas automatiquement transmise aux processus enfants.

La commande export sous Linux marque la variable pour qu’elle soit ajoutée à l’environnement des commandes lancées ensuite. Elle ne la rend pas permanente et ne la transmet pas au shell parent. Voici comment le vérifier, choisir le bon fichier de démarrage et éviter de placer un secret en clair dans votre environnement.

Tux transmet une variable exportée du shell parent vers deux processus enfants
Une variable exportée est transmise aux processus créés ensuite par le shell.

Comprendre ce que change export

Dans Bash, commencez par créer une variable sans l’exporter :

APP_ENV=production
printf '%s\n' "$APP_ENV"
bash --noprofile --norc -c 'printf "enfant=<%s>\n" "${APP_ENV-}"'

La première commande affiche production. Le nouveau processus Bash affiche une valeur vide, car il n’a pas reçu APP_ENV. Exportez maintenant la variable et recommencez :

export APP_ENV
bash --noprofile --norc -c 'printf "enfant=<%s>\n" "$APP_ENV"'

Le shell enfant affiche cette fois production. Vous pouvez aussi affecter et exporter en une seule ligne :

export APP_ENV=production

export est une commande interne du shell, pas un programme Linux autonome. La règle reste la même : les processus enfants héritent des variables exportées au moment de leur création. Une modification faite ensuite dans le parent ne change pas l’environnement d’un processus déjà lancé. Un script exécuté ne peut pas non plus modifier l’environnement du terminal qui l’a démarré.

Vérifier la variable dans le shell et dans un processus enfant

Ne vous contentez pas d’un echo dans le terminal courant. Vérifiez la valeur, son attribut d’export et ce qu’un enfant reçoit réellement :

printf '%s\n' "$APP_ENV"
declare -p APP_ENV
printenv APP_ENV
env | grep '^APP_ENV='
bash --noprofile --norc -c 'printenv APP_ENV'

Avec Bash, declare -p affiche notamment l’attribut -x quand la variable est exportée. printenv et env ne voient que l’environnement exporté. La dernière commande constitue le contrôle le plus utile avant d’accuser le script : elle démarre un Bash propre, sans charger les fichiers de profil, puis lit la variable reçue.

Pour tester une commande avec un environnement minimal, utilisez env -i et fournissez seulement ce dont elle a besoin :

env -i PATH=/usr/bin:/bin APP_ENV=test \
  bash --noprofile --norc -c 'printenv APP_ENV; command -v id'

Ce test repère les scripts qui dépendent sans le dire de votre session interactive. Conservez un PATH minimal, sinon même les commandes usuelles peuvent devenir introuvables. Si c’est justement votre problème, le guide PATH sous Linux explique comment tester un ajout sans masquer un binaire système.

Rendre une variable persistante dans le bon fichier

La ligne export APP_ENV=production disparaît à la fermeture du shell. Pour la retrouver dans vos prochains terminaux Bash interactifs, ajoutez-la généralement à ~/.bashrc. Sauvegardez d’abord le fichier et contrôlez qu’une ligne identique n’existe pas déjà :

cp -a ~/.bashrc ~/.bashrc.bak-$(date +%F-%H%M)
grep -n '^export APP_ENV=' ~/.bashrc

Modifiez ensuite le fichier avec votre éditeur et gardez une seule définition :

export APP_ENV=production

Avant de recharger, faites vérifier la syntaxe par Bash :

bash -n ~/.bashrc
. ~/.bashrc
printenv APP_ENV

Si bash -n retourne une erreur, ne rechargez pas le fichier. Corrigez la ligne indiquée ou restaurez la sauvegarde. Évitez aussi d’ajouter la même instruction à chaque exécution d’un script : vous finirez avec plusieurs définitions contradictoires.

~/.bashrc vise les shells Bash interactifs non-login. Un shell de connexion lit plutôt /etc/profile, puis le premier fichier disponible parmi ~/.bash_profile, ~/.bash_login et ~/.profile. Zsh utilise notamment ~/.zshrc. Vérifiez votre shell avant de modifier un fichier au hasard :

printf 'shell=%s\n' "$SHELL"
ps -p $$ -o comm=

Une tâche cron, un service systemd ou une application lancée par l’interface graphique ne charge pas forcément votre ~/.bashrc. Déclarez alors la variable dans la configuration de ce service ou de cette tâche. Ne contournez pas le problème en faisant charger tout votre profil interactif par un service.

Éviter les erreurs de syntaxe et les variables perdues avec sudo

Une affectation shell ne tolère aucun espace autour du signe égal. La première ligne est valide, la seconde tente d’exécuter une commande nommée APP_ENV :

APP_ENV="production Europe"
APP_ENV = "production Europe"

Le nom doit commencer par une lettre ou un soulignement, puis contenir uniquement des lettres, chiffres ou soulignements. Utilisez par exemple APP_ENV, pas APP-ENV.

sudo filtre une partie de l’environnement par défaut. Une variable visible dans votre shell peut donc manquer dans la commande privilégiée :

printenv APP_ENV
sudo printenv APP_ENV

N’utilisez pas sudo -E par réflexe. Pour une commande ponctuelle et non sensible, passez explicitement la valeur attendue si la politique sudo l’autorise. Pour un service, déclarez-la dans son unité ou dans un fichier d’environnement protégé. Vous saurez ainsi exactement quelles variables arrivent au programme privilégié.

Ne pas exporter un secret en clair

Un jeton, un mot de passe ou une clé API saisis avec export SECRET=... peuvent rester dans l’historique du shell. Ils sont aussi transmis à tous les processus enfants et peuvent finir dans un rapport de diagnostic, un dump ou une commande qui affiche l’environnement.

Évitez donc les secrets dans ~/.bashrc, ~/.profile et les scripts versionnés. Utilisez le gestionnaire de secrets de l’application, les identifiants systemd quand ils sont disponibles, ou un fichier dédié lisible uniquement par le compte du service. L’article sur l’historique Bash montre comment retirer une ligne sensible, mais un secret déjà exposé doit aussi être révoqué ou remplacé.

Quand la variable n’est plus utile, retirez-la du shell courant et vérifiez sa disparition :

unset APP_ENV
printenv APP_ENV
printf 'code=%s\n' "$?"

printenv ne doit rien afficher et retourne normalement un code différent de zéro. Supprimez aussi la définition persistante du fichier de démarrage concerné, puis ouvrez un nouveau terminal pour valider. Pour approfondir les attributs de variables et les fichiers chargés au démarrage, consultez les pages de manuel Debian de bash-builtins et de Bash.