Je suis nouveau sur Ubuntu.
J'ai écrit un script pour ajouter un répertoire à l'environnement PATH. Lorsque je lance le script, il fonctionne correctement et le répertoire est ajouté à PATH. Mais il semble que le changement ne dure que jusqu'à la fin du script au lieu de durer toute la session. Quand je regarde le PATH après l'exécution du script, le répertoire n'est plus là. Aucune suggestion?
Il y a deux choses à retenir:
Les commandes, y compris les scripts, conservent leur environnement pendant toute la durée de l'exécution de la commande.
Les commandes héritent de l'environnement du processus parent. Pour les commandes lancées via Shell, elles hériteront du shell.
Donc si vous faites PATH=$PATH:/my/dir
cela ne durera que pour la durée des scripts. Pour le rendre permanent, le Shell parent doit être conscient du changement. La meilleure façon de le faire serait d'écrire sur ~/.bashrc
si vous utilisez un fichier rc bash ou approprié pour votre shell. Ainsi, nous pouvons utiliser >> pour ajouter au fichier
echo PATH=$PATH:/my/dir >> ~/.bashrc
Et quand le script se termine, lancez
source ~/.bashrc
afin que le shell relise la configuration et soit au courant des modifications. Désormais, chaque commande exécutée dans Shell et chaque nouveau shell interactif hériteront de la nouvelle variable PATH.
Les deux étapes peuvent être réunies dans une fonction car (du moins pour bash), les fonctions sont exécutées dans l’environnement Shell actuel. Par conséquent, contrairement à un script qui exécute une partie source
, appeler source
à partir d’une fonction affecte le Shell actuel.
La réponse de Sergiy Kolodyazhnyy identifie le problème ici: les scripts sont exécutés dans un shell séparé du shell qui les appelle, et les commandes qui affectent le shell lui-même, telles que l'attribution de variables ou la modification du répertoire de travail, ne le sont pas. affecte le shell appelant, seul le shell enfant et (s’ils export
variables à l’environnement) ses enfants.
Vous pouvez jouer avec cela en utilisant les variables humbles de Shell ...
$ foo=bar
$ echo $foo
bar
$ echo -e "foo=baz \n"'echo $foo' > script
$ cat script
foo=baz
echo $foo
$ bash script
baz
$ echo $foo
bar
Bien que, comme le montre Eliah Kagan dans cette réponse , il est plus facile de le faire avec des sous-shell.
J'écris cette réponse au cas où vous ne voudriez pas ajouter en permanence le répertoire à votre PATH, mais uniquement à la session Shell en cours.
Pour ce faire, vous devez simplement exécuter le script dans le shell actuel . Ceci est fait avec la commande source
qui est abrégée en .
(point).
Compte tenu de cette version légèrement simplifiée de votre script ...
read -rp "What did you want to add to PATH? "
[ -d "$REPLY" ] &&
PATH="$PATH:$(readlink -m $REPLY)" &&
echo "OK, adding $REPLY to PATH" &&
echo "$PATH" ||
echo "seems like $REPLY is not a directory"
Notez que je reçois le même résultat que vous lorsque je lance le script de la manière habituelle:
$ ./add-to-path
What did you want to add to PATH? /home/zanna/playground
OK, adding /home/zanna/playground to PATH
/home/zanna/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/zanna/playground
$ echo $PATH
/home/zanna/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
Mais lorsque je source
le script, il fonctionne comme prévu:
$ . add-to-path
What did you want to add to PATH? /home/zanna/playground
OK, adding /home/zanna/playground to PATH
/home/zanna/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/zanna/playground
$ echo $PATH
/home/zanna/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/zanna/playground
Je vais ajouter trois apartés:
~/.profile
plutôt qu'à ~/.bashrc
, car ~/.bashrc
provient de chaque Bash Shell interactif, y compris des shells démarrés à partir du shell actuel - cela signifie que des shells enfants pourraient se retrouver très longtemps PATHs, car ils héritent de PATH et s’y ajoutent lorsqu’ils sources ~/.bashrc
. En revanche, ~/.profile
ne provient généralement que de la connexion (ou des shells de connexion).export
lorsque vous affectez à PATH car il s'agit déjà d'une variable d'environnement: dans un sens, elle est déjà exportée et le restera: une affectation à PATH sera toujours héritée par les processus enfants (mais pas par les processus parents, comme vous avez découvert!) sans être explicitement export
ed.J'ai cité les variables REPLY
et PATH
dans l'ensemble. C'est une bonne idée car il peut y avoir des espaces ou d'autres caractères qui déclenchent des extensions du shell. Cependant, un effet secondaire de ceci est que ~
n'est pas développé, le script est donc susceptible de renvoyer des éléments tels que
looks like ~/some-existing-dir is not a directory
ce qui est vrai (en prenant ~
littéralement) mais pas très utile. Peut-être que le script devrait en avertir l'utilisateur ...