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

51

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

source ~/.bashrc

mais si j'écris ceci dans un script shell et l'exécute, rien ne se passe. Pourquoi?
Est-ce qu'il y a un moyen de faire ça?

Mon script:

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

Aussi essayé .(point) au lieu de source. Même résultat.

Shantanu
la source

Réponses:

26

Un script shell est exécuté dans sa propre instance de 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 sourcecommande 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'
Florian Diesch
la source
Merci pour votre réponse rapide. Votre solution fonctionne peut-être mais je dois éditer le fichier bashrc manuellement pour enregistrer la ligne 'aliac brc = ....'. J'essaie de développer une interface graphique pour changer la variable d'environnement. Donc, je ne peux pas éditer le fichier bashrc d'un autre ordinateur manuellement.
Shantanu
1
Vous devez exécuter source ~/.bashrcle shell dont vous souhaitez modifier l'environnement. Vous ne pouvez pas le changer d'un autre processus. Peut-être que (globalement) l'ajout de cet alias pourrait faire partie du processus d'installation de votre interface graphique.
Florian Diesch
1
alors est-ce que je mets votre commande alias plus tôt dans le script, puis invoquez brc quand je veux utiliser mon source .bashrc ou j'ai besoin de mettre cette commande alias dans un fichier quelque part?
user137717
Ce que j'ai fini par faire est une extension de la réponse de Florian Diesch. Vous pouvez simplement utiliser un alias multiligne: alias brc = 'chmod a + x ~ / .bashrc; source ~ / .bashrc 'Je suis encore assez nouveau, alors je ne suis pas sûr que cela soit considéré comme une «mauvaise pratique». Cela fonctionne cependant.
A_user_appear
13

Votre .bashrccommence habituellement:

# 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.

Ravi Nankani
la source
Au moins depuis 16.04 et probablement avant, Ubuntu par défaut .bashrcutilise un moyen plus fiable de vérifier que le shell est interactif. /etc/bash.bashrca toujours le test PS1.
Zanna
12

Essayer:

exec bash

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

Alin Andrei
la source
9
Ceci remplace le processus bash actuel par un nouveau. Ce n'est pas beaucoup plus court ni plus facile que d'utiliser, sourcemais détruit toutes les variables et que l'utilisateur a définies manuellement - ce qui peut être ou ne pas être ce que vous voulez.
Florian Diesch
Attendez, dans le contexte d'un script Shell avec d'autres commandes après le sourcing bashrc, placez-vous les commandes qui nécessitent le nouvel état bash après cela exec bash, la façon dont je le comprends commande après restera dans les mêmes paramètres bash qu'auparavant?
Tatsu
11

Je veux compléter la réponse de Ravi :

Ce comportement est spécifique à Ubuntu (et probablement à la plupart des distributions dérivées), car votre ~/.bashrcfichier par défaut 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, car tous les scripts sont exécutés dans un shell non interactif , et par la suite tous les fichiers dont vous sourcehériterez.

eval pirater

J'ai découvert un vilain bidouillage pour contourner spécifiquement Ubuntu, en utilisant à la evalplace de source:

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

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

Sachez qu’il s’agit d’un nombre magique qui pourrait ne pas fonctionner avec toutes 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 préférable d’utiliser le #!/usr/bin/env bashformulaire, mais de cette manière, vous ne pouvez pas démarrer le shell avec des arguments .
  • L'utilisation de -ia ses propres conséquences, parmi lesquelles les programmes inviteront les utilisateurs à interagir, ce qui n'est généralement pas destiné aux scripts. Par exemple, l'installation de debpackages peut arrêter le script à l' dpkg configureinvite .
  • J'ai d'abord essayé d'utiliser set -iet set +id'activer et de désactiver la fonctionnalité là où j'en avais besoin, mais cela ne fonctionne pas .
stefanmaric
la source
2

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

#!/usr/bin/env bash case

au lieu du plus simple, #!/usr/bin/envon laisse les arguments à l’interprète, ce qui 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 :)

Nikksno
la source