web-dev-qa-db-fra.com

Impossible de réussir la source .bashrc à partir d'un script shell

Normalement, nous pouvons source le fichier ~/.bashrc en utilisant cette commande

source ~/.bashrc

mais si j'écris ceci dans un script Shell et que je l'exécute, rien ne se passe. Pourquoi?
Y a-t-il un moyen de faire ça?

Mon script:

#!/bin/bash
chmod a+x ~/.bashrc
source ~/.bashrc

Nous avons également essayé . (point) au lieu de sourcename__. Même résultat.

49
shantanu

Un script Shell est exécuté dans sa propre instance Shell. Tous les paramètres de variable, définitions de fonction et autres affectent uniquement cette instance (et peut-être ses enfants), mais pas le shell appelant. Ils sont donc supprimés à la fin du script.

En revanche, la commande source ne démarre pas une nouvelle instance de shell mais utilise le shell actuel pour que les modifications restent.

Si vous voulez qu'un raccourci lise votre .bashrc, utilisez une fonction Shell ou un alias à la place d'un script Shell, comme

alias brc='source ~/.bashrc'
25
Florian Diesch

Essayer:

exec bash

Cela devrait recharger ~/.bashrc, ~/.bash_aliases, etc.

12
Alin Andrei

Votre .bashrc commence généralement par:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

Étant donné que votre script n'a pas défini PS1 (car il n'est pas interactif), il ne réinitialise pas le chemin car il se ferme tôt. Pour démontrer, modifiez votre script:

    #!/bin/bash
    chmod a+x ~/.bashrc
    PS1='$ '
    source ~/.bashrc

cela permettra maintenant à vos scripts de fonctionner avec le nouveau .bashrc. Remarque: une fois votre script terminé, env sera défini sur ce qu'il était avant de démarrer le script. Les modifications seront répercutées au prochain démarrage d’un terminal.

12
ravi nankani

Je veux compléter réponse de Ravi :

Ce comportement est spécifique à Ubuntu (et probablement à la plupart des distributions dérivées), car votre fichier par défaut ~/.bashrc commence par un court-circuit, Ubuntu 18.04, par exemple:

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

Cela arrêtera l'évaluation du fichier s'il est exécuté dans un shell non interactif, ce qui est le cas de votre script depuis tous les scripts sont exécutés dans un shell non interactif , et par la suite chaque fichier source héritera de cette propriété.

eval hack

J'ai découvert un vilain bidouillage pour contourner spécifiquement Ubuntu, en utilisant eval au lieu de source:

eval "$(cat ~/.bashrc | tail -n +10)"

Il saute simplement les quelques premières lignes et évalue le reste du ~/.bashrc afin que le reste soit évalué et modifie l'exécution en cours.

Sachez que c'est un nombre magique et qu'il est possible que cela ne fonctionne pas avec les versions d'Ubuntu; mais peut être une bonne solution si vous construisez des scripts pour des systèmes plus ou moins connus.

Une solution plus sophistiquée pourrait impliquer l’utilisation de regex pour cibler les bits spécifiques qui arrêtent l’évaluation.

Alternative Shebang

Une autre alternative qui pourrait mieux fonctionner dans certains scénarios consiste à forcer le script à s'exécuter dans un shell interactif en ajoutant un indicateur dans le Shebang :

#!/bin/bash -i

Soyez conscient de certaines choses:

  • Il est meilleure pratique d'utiliser le formulaire #!/usr/bin/env bash mais de cette façon, vous ne pouvez pas démarrer le shell avec des arguments .
  • L'utilisation de -i a son propre ensemble de conséquences, parmi lesquelles les programmes invitent l'utilisateur à interagir et ceci n'est généralement pas destiné aux scripts. Par exemple, l'installation de packages deb peut arrêter le script à dpkg configure prompts .
  • J'ai d'abord essayé d'utiliser set -i et set +i pour activer et désactiver la fonctionnalité là où j'en avais besoin, mais cela ne fonctionne pas .
10
stefanmaric

Aucune des autres méthodes ne fonctionnait pour moi [source /path/to/file vs . ./path/to/file, alias, etc ...], jusqu'à ce que, grâce à ce tutoriel , j'ai découvert que:

#!/usr/bin/env bash Shebang

au lieu du plus simple #!/usr/bin/env, les arguments sont transmis à l’interprète, ce qui, à mon avis, est la clé ici - voir ce document pour plus d’informations.

En tout état de cause, si les commandes de source, sous quelque forme que ce soit, ne fonctionnent pas pour vous, essayez de vérifier votre Shebang, c'est peut-être le problème :)

2
Nikksno