[shell] Variable sous Unix

[Résolu/Fermé]
Signaler
-
 Mutin -
Bonjour,
J'ai commencé hier principalement par amusement à "jouer" avec Terminal sur Mac OS:X, après mettre familiarisé un minimum avec les commandes Unix de bases j'ai décider de crée quelques scripts vraiment basiques, je rencontre néanmoins un problèmes que je n'ai pas réussi a résoudre à savoir les variables.
J'ai tenté à plusieurs reprises de crée une variable "datee" pour afficher la date justement.
J'ai donc utilisé la commande datee=$(date). Je tape ensuite $datee aucune réponse, echo $datee la la date apparait, mais lorsque je ferme Terminal et que je le reouvre plus aucune trace de ma variable.
Ma question est donc la suivante à quel niveau réside mon erreur :p ?

9 réponses

Messages postés
30131
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
26 septembre 2021
7 176
Petites précisions pour que tu y vois plus clair. Lorsque tu lances un programme, celui-ci est susceptible de lire des fichiers à son démarrage, généralement postfixés "rc" (comme run configuration ?). Par exemple bash lit des fichiers bashrc, vim des fichiers vimrc et ainsi de suite.

Pour le jargon, on appelle shell un truc qui interprète des lignes de commandes shell (souvent fortement inspirées du monde d'unix). Il existe différentes sortes de shell (bash, sh, dash, zsh, ksh) généralement postfixées par sh (comme shell). Les scripts shell portent généralement une extension ".sh". Ils ne peuvent être exécutés que si les droits en exécution sont activés (par exemple à l'aide d'un chmod).

Le shell s'initialise

Ces scripts peuvent être globaux à tous les utilisateurs (dans ce cas il sont dans /etc) ou spécifique à un utilisateur (et dans ce cas ils sont stockés dans son home directory, par exemple /home/mando). Afin de ne pas polluer ton home, les fichiers de profils sont cachés : ils sont préfixés par un ".". C'est notamment pourquoi ils n'apparaissent pas par défaut dans ton explorateur de fichiers (par exemple dolphin ou nautilus).

Ainsi, bash repose sur deux fichiers :
- /etc/bash.bashrc (ou nom proche), le profil global
- /home/mando/.bashrc (alias ~mando/.bashrc, alias ~/.bashrc si tu es loggué en mando) pour l'utilisateur mando.

Ces deux fichiers sont lus à l'initialisation du bash au travers de la commande shell "source". Cela signifie que le script shell contenu dans ces fichiers n'est pas exécuté dans un sous processus du terminal que tu viens de lancer, mais comme si on avait directement tapé ces commandes shell dans ledit terminal.

Lancer un script : source vs exécution

Exemple : suppose que plop.sh contienne ceci :

#!/bin/bash
export pouet="plop"


Voici ce qui se passe (la commande env affiche toutes les variables d'environnement, grep permet de filtrer les résultats) :

(mando@aldur) (~) $ source plop.sh
(mando@aldur) (~) $ env | grep pouet
pouet=plop


Ouvrons un autre terminal. Comme chaque terminal utilise son propre environnement shell, sans surprise, cette variable n'apparaît pas :

(mando@aldur) (~) $ env | grep pouet
(mando@aldur) (~) $


Forcément car, la portée de la variable pouet est limitée à son shell. Maintenant, lançons dans ce second terminal notre script, mais pas via la commande source :

(mando@aldur) (~) $ chmod a+x plop.sh
(mando@aldur) (~) $ ./plop.sh
(mando@aldur) (~) $ env | grep pouet
(mando@aldur) (~) $


Fichtre, la variable n'apparaît pas ! Et pour cause. Le script plop.sh est lancé en tant que sous-processus de ce terminal. Il ne peut donc pas intervenir sur les variables de la console. Si d'aventure ce script manipulait une variable qui existe déjà dans la console (par exemple la variable d'environnement PATH), une fois revenu dans le terminal, on s'apercevrait que le script ne l'a modifiée qu'au niveau du script. La variable PATH n'est pas modifiée dans la console.

Ça c'est la nuance entre lancer un script shell en tant qu'exécutable et via la commande source.

La portée d'une variable shell

Comme nous venons de le voir, la portée d'une variable se limite à son shell. Le fait de lancer un script shell en tant qu'exécutable revient à lancer un sous shell qui n'impacte que les variables de son environnement.

Modifions un peu notre script plop.sh :

#!/bin/sh
echo "La variable a vaut [$a]"
# Comme le montre la commande "env", HOME contient 
# le chemin vers ton home directory
echo $HOME


... et voyons ce qui se passe si la variable a est initialisée dans le shell dans le script qui lance le shell :

(mando@aldur) (~) $ echo $HOME
/home/mando
(mando@aldur) (~) $ ./plop.sh
La variable a vaut []
/home/mando


Diantre, la variable a n'est pas initialisée, alors que HOME apparaît correctement ! En fait c'est normal. La variable a n'a pas été exportées. Cela signifie qu'elle n'est pas propagée auprès des sous-shells (notamment celui du script plop.sh). Exportons cette variable :

(mando@aldur) (~) $ export a
(mando@aldur) (~) $ ./plop.sh
La variable a vaut [tapir]
/home/mando


Et hop, grâce au export, la variable a est bien propagée auprès du sous shell (celui du script plop.sh). On a donc augmenté sa portée. Traditionnellement, on initialise et on exporte simultanément une variable qui est susceptible de servir dans les sous-shells. C'est typiquement ce qui est fait pour les variables d'environnements initialisées par le système (HOME, PATH etc...).

Mais il y a vraiment des sous-shells ?!?

Oui et voici la preuve en image. Modifions un peu notre script plop.sh :

#!/bin/sh
ps -faux


La commande "ps -faux" affiche la table des processus. Exécutons notre script :

(mando@aldur) (~) $ ./plop.sh


Si on se promène un peu dans les lignes qui s'affichent, on trouve ce passage, particulièrement éloquent :

mando     ...   17:37   0:00  \_ /bin/bash
mando     ...   17:54   0:00      \_ /bin/sh ./plop.sh
mando     ...   17:54   0:00          \_ ps -faux


Ma console utilise un bash (1ère ligne, 1er processus), a lancé un script shell interprété par sh (2e ligne, 2ème processus), qui lui même a lancé un processus "ps -faux" (3ème ligne). On retrouve bien le fait que bash a manipulé un sous-shell (sh) dans lequel la commande ps a été lancée.

En espérant que c'est plus clair pour toi ;-)
Bonne chance
7
Merci

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

CCM 42674 internautes nous ont dit merci ce mois-ci

Salut,

Chapeau bas Miss ;-))
Merci beaucoup \o/

Chapeau *_*
Messages postés
30131
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
26 septembre 2021
7 176
En fait il faudrait que tu lises un tutoriel sur le bash, en particulier le rôle du mot clé export. En fait les variables d'un shell ne sont pas propagées vers un shell fils à moins d'utiliser le mot clé export. C'est donc une manière de propager une variable d'un terminal (le shell) vers un script lancé dans ce terminal (qui est un sous shell).

En terme syntaxique, tu peux également utiliser les backquotes (alt gr 7) pour évaluer le résultat d'une commande :

#!/bin/sh

mydate=`date`
echo ${mydate}


Je crois que $(...) est supporté uniquement en bash, `...` est supporté par tous les shells (sh, bash, tcsh...). Bon ceci dit, je me trompe peut être et 99% des gens utilisent bash, donc ce n'est pas fondamental.

Bonne chance
Messages postés
119
Date d'inscription
mardi 22 décembre 2009
Statut
Membre
Dernière intervention
11 juillet 2010
23
Bonjour,

1/ Lorsque dans un terminal tu tapes $datee, le shell essaie d'executer le contenu de la variable datee.
Pour info (je ne connais pas l'Unix utilise sur les Mac), mais j'essaierais plutot de faire:
datee=`date`
pour recuperer le resultat de la *commande* /bin/date et la stockee dans ta variable datee.
Attention, il s'agit bien de ` et non pas de '

2/ Ce qu'il faut bien comprendre, c'est que la variable est valable uniquement dans le process en cours. Ainsi la variable n'existe *pas* dans un nouveau terminal, que tu fermes le premier ou non.

HTH
Salut,

C'est normal. Ce n'est pas une erreur.
Une variable a une durée de vie et une portée.

Une fois que tu as quitter la session de ton shell la variable disparaît.
Pour garder la valeur de la variable il faut l'enregistrée dans le fichier d'initialisation de ton shell.

Un exemple sous debian
lami20j@debian:~$ echo $datee

lami20j@debian:~$ echo 'datee=$(date)' >> .bashrc  
lami20j@debian:~$ . .bashrc
lami20j@debian:~$ echo $datee
lundi 28 décembre 2009, 17:32:51 (UTC+0100)



Et après fermeture/ouverture d'un terminal
lami20j@debian:~$ echo $datee
lundi 28 décembre 2009, 17:33:51 (UTC+0100)
Tout d'abord merci à tous pour vos réponse, parce que je vous avoue que c'est la première fois que j'y touche et je suis légèrement perdu :p

Donc il faudrait si j'ai bien compris pour que ma variable sont enregistré que j'inscrive echo datee=$(date) dans le fichier d'initialisation de mon shell, ma question est donc la suivante, ou trouver ce fichier ?

Je ne sais pas si cela est vraiment important ici mais j'utilise bash
Re,

Affiche le résultat de
echo $SHELL
Ca me donne :

noname:bin Tom$ echo $SHELL
/bin/bash

quand je rentre : open bash

Une nouvelle fenêtre s'ouvre avec :

Last login: Mon Dec 28 18:59:13 on ttys001
/bin/bash ; exit;
noname:~ Tom$ /bin/bash ; exit;
bash-3.2$
Re,

N'ouvre pas un nouveau shell (attention je n'ai pas dit terminal), tu mélanges les pinceaux est ce n'est pas bien ;-)

Quand tu vois l'invité noname:bin Tom$ alors tu peux commencer l'édition de ton fichier qui doit être .bashrc

Pour vérifier fait un
 ls -al .bashrc
Merci beaucoup à vous tous pour vos conseils et explications

Alors là : O

Chapeau bas de ma part aussi !!!!!

Je ne crois pas qu'il est possible d'être plus claire ; )

@++ : )
Messages postés
30131
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
26 septembre 2021
7 176
Merci pour les compliments, ça fait toujours chaud au cœur ;-)

Passez de bonnes fêtes !