Différence entre .bashrc et .bash_profile

449

Quelle est la différence entre .bashrcet .bash_profileet lequel dois-je utiliser?

cfischer
la source
2
Voir aussi cette question similaire sur ubuntu.stackexchange.com/questions/1528/bashrc-or-bash-profile
Stefan Lasiewski le
Si vous souhaitez une explication plus complète .profile, consultez également cette question: superuser.com/questions/789448/…
Flimm
Cette réponse couvre également certains aspects stackoverflow.com/questions/415403/…
Sergey Voronezhskiy

Réponses:

517

Traditionnellement, lorsque vous vous connectez à un système Unix, le système lance un programme pour vous. Ce programme est un shell, c’est-à-dire un programme conçu pour lancer d’autres programmes. C'est un shell en ligne de commande: vous démarrez un autre programme en tapant son nom. Le shell par défaut, un shell Bourne, lit les commandes à partir du ~/.profilemoment où il est appelé en tant que shell de connexion.

Bash est un shell de type Bourne. Il lit les commandes à partir du ~/.bash_profilemoment où il est appelé en tant que shell de connexion, et si ce fichier n'existe pas¹, il essaie de lire à la ~/.profileplace.

Vous pouvez appeler un shell directement à tout moment, par exemple en lançant un émulateur de terminal dans un environnement graphique. Si le shell n'est pas un shell de connexion, il ne lit pas ~/.profile. Lorsque vous démarrez bash en tant que shell interactif (c.-à-d. Pour ne pas exécuter de script), il lit ~/.bashrc(sauf lorsqu'il est appelé en tant que shell de connexion, il ne lit que ~/.bash_profileou ~/.profile.

Donc:

  • ~/.profile est l'endroit idéal pour mettre des éléments qui s'appliquent à l'ensemble de votre session, tels que les programmes que vous souhaitez démarrer lorsque vous vous connectez (mais pas les programmes graphiques, ils vont dans un fichier différent) et les définitions de variable d'environnement.

  • ~/.bashrcest l'endroit idéal pour mettre des éléments qui ne s'appliquent qu'à bash lui-même, tels que les définitions d'alias et de fonctions, les options du shell et les paramètres d'invite. (Vous pouvez aussi y mettre des raccourcis clavier, mais pour bash ils vont normalement dans ~/.inputrc.)

  • ~/.bash_profilepeut être utilisé à la place de ~/.profile, mais il est lu uniquement par bash, pas par un autre shell. (Ceci est principalement une préoccupation si vous voulez que vos fichiers d'initialisation fonctionnent sur plusieurs machines et que votre shell de connexion ne les traite pas toutes.) C'est un endroit logique à inclure ~/.bashrcsi le shell est interactif. Je recommande le contenu suivant dans ~/.bash_profile:

    if [ -r ~/.profile ]; then . ~/.profile; fi
    case "$-" in *i*) if [ -r ~/.bashrc ]; then . ~/.bashrc; fi;; esac

Sur les ordinateurs modernes, il y a une complication supplémentaire liée à ~/.profile. Si vous vous connectez dans un environnement graphique (qui est, si le programme où vous tapez votre mot de passe est en cours d' exécution en mode graphique), vous ne recevez pas automatiquement un shell de connexion qui lit ~/.profile. En fonction du programme de connexion graphique, du gestionnaire de fenêtres ou de l'environnement de bureau que vous exécutez par la suite, et de la manière dont votre distribution a configuré ces programmes, votre ~/.profilelecture ou non. Si ce n'est pas le cas, il existe généralement un autre endroit où vous pouvez définir des variables d'environnement et des programmes à lancer lorsque vous vous connectez, mais il n'existe malheureusement pas d'emplacement standard.

Notez que vous pouvez voir ici et là des recommandations pour insérer des définitions de variable d'environnement ~/.bashrcou toujours lancer des shells de connexion dans des terminaux. Les deux sont de mauvaises idées. Le problème le plus courant avec l'une ou l'autre de ces idées est que vos variables d'environnement ne seront définies que dans des programmes lancés via le terminal, et non dans des programmes lancés directement avec une icône, un menu ou un raccourci clavier.

¹ Pour compléter, sur demande: si .bash_profilen’existe pas, bash essaie également .bash_loginavant de revenir à .profile. N'hésitez pas à oublier qu'il existe.

Gilles
la source
11
+1 pour le bon post. AUSSI merci d’avoir ajouté une section sur "login graphique vs login shell" ... j’ai eu le problème suivant: je pensais que ~ / .profile serait TOUJOURS exécuté pour un graphique / shell ... mais il ne s’exécute pas lorsque l’utilisateur se connecte via connexion graphique. Merci d'avoir résolu ce mystère.
Trevor Boyd Smith
4
@ Gilles: Pourriez-vous expliquer plus en détail, avec des exemples, pourquoi il est malavé d'exécuter un shell de connexion dans chaque terminal? Est-ce seulement un problème avec le bureau Linux? (Je suppose que sous OS X Terminal exécute un shell de connexion à chaque fois, et je n'ai jamais remarqué d'effets secondaires (bien que j'utilise habituellement iTerm). Mais je ne peux pas penser à beaucoup de variables d'environnement qui m'importent en dehors de un terminal. (Peut-être HTTP_PROXY?))
iconoclast
2
@Brandon Si vous exécutez un shell de connexion dans chaque terminal, les variables d'environnement fournies par l'environnement seront écrasées. Dans la vie de tous les jours, vous pouvez vous en sortir, mais cela viendra vous mordre tôt ou tard, lorsque vous souhaitez configurer différentes variables dans un terminal (par exemple, pour essayer une version différente d'un programme): shell de connexion remplacerait vos paramètres locaux.
Gilles
4
L'instruction ~/.bash_profilepeut être utilisée à la place de ~/.profile, mais vous devez également inclure ~/.bashrcsi le shell est interactif. est trompeur car ce sont des problèmes orthogonaux. Peu importe si vous utilisez ~/.bash_profileou ~/.profiledevez inclure ~/.bashrcdans celui que vous utilisez si vous voulez que les paramètres à partir de là aient un effet dans le shell de connexion.
Piotr Dobrogost
3
@Gilles Bien sûr, mais la façon dont la phrase est formulée dans la réponse suggère que le besoin d'inclure ~/.bashrca quelque chose à voir avec le choix ~/.bash_profileplutôt que ~/.profilece qui n'est pas vrai. Si une personne est incluse ~/.bashrcdans n'importe quel type de script en cours de connexion au moment de la connexion (ici, c'est ~/.bash_profileou ~/.profile), c'est parce qu'il veut que les paramètres ~/.bashrcsoient appliqués au shell de connexion de la même manière qu'ils sont appliqués à un shell autre que de connexion.
Piotr Dobrogost
53

De ce court article

Selon la page de manuel bash, .bash_profile est exécuté pour les shells de connexion, alors que .bashrc est exécuté pour les shells interactifs autres que les pseudonymes.

Qu'est-ce qu'un shell avec ou sans login?

Lorsque vous vous connectez (par exemple, tapez nom d'utilisateur et mot de passe) via la console, soit physiquement assis sur la machine lors du démarrage, soit à distance via ssh: .bash_profile est exécuté pour configurer les éléments avant l'invite de commande initiale.

Toutefois, si vous êtes déjà connecté à votre ordinateur et ouvrez une nouvelle fenêtre de terminal (xterm) dans Gnome ou KDE, alors .bashrc est exécuté avant l'invite de commande de la fenêtre. .bashrc est également exécuté lorsque vous démarrez une nouvelle instance bash en tapant / bin / bash dans un terminal.

Jarvin
la source
12
Légères mises à jour: "Exécuté" est probablement un terme légèrement trompeur, ils proviennent tous les deux. Exécuté semble fonctionner comme un script fork / exec yadda yadda. Il est exécuté dans le contexte du shell actuel. Plus important encore, .bashrc est exécuté beaucoup plus souvent. Il est exécuté à chaque exécution de script bash, et également si vous ne possédez pas de fichier .bash_profile. En outre, en fonction de la configuration de votre xterms, vous pouvez créer un shell qui code .bash_profile
Rich Homolka
36

Autrefois, quand les pseudo-billets n'étaient pas pseudo et en fait, les dactylographes et UNIX étaient accédés par des modems si lents que vous pouviez voir chaque lettre être imprimée sur votre écran, l'efficacité était primordiale. Pour améliorer quelque peu l'efficacité, vous avez eu l'idée d'une fenêtre de connexion principale et de toutes les autres fenêtres avec lesquelles vous travailliez réellement. Dans votre fenêtre principale, vous souhaitez recevoir des notifications pour tout nouveau courrier, éventuellement exécuter d’autres programmes en arrière-plan.

Pour supporter cela, les shells ont créé un fichier .profilespécifiquement sur les "shells de connexion". Cela ferait la spéciale, une fois une session de configuration. Bash a étendu cela un peu en regardant d'abord .bash_profile avant .profile. Ainsi, vous ne pouvez enregistrer que des choses là-dedans (pour ne pas bousiller Bourne Shell, etc., qui ont également regardé .profile). D'autres shells, non connectés, se contentent de créer le fichier rc, .bashrc (ou .kshrc, etc.).

C'est un peu un anachronisme maintenant. Vous ne vous connectez pas à un shell principal autant que vous vous connectez à un gestionnaire de fenêtres gui. Il n'y a pas de fenêtre principale différente des autres fenêtres.

Ma suggestion - ne vous inquiétez pas de cette différence, elle est basée sur un style plus ancien d’utilisation de Unix. Éliminez la différence dans vos fichiers. Le contenu entier de .bash_profile devrait être:

[ -f $HOME/.bashrc ] && . $HOME/.bashrc

Et mettez tout ce que vous voulez réellement mettre en .bashrc

N'oubliez pas que .bashrc provient de tous les shells, interactif et non interactif. Vous pouvez court-circuiter le sourcing pour les shells non interactifs en plaçant ce code près du sommet de .bashrc:

[[ $- != *i* ]] && return

Rich Homolka
la source
6
C'est une mauvaise idée, voir ma réponse . En particulier, vos variables d'environnement ne seront définies que dans les programmes lancés via le terminal, et non dans les programmes lancés directement avec une icône, un menu ou un raccourci clavier.
Gilles le
4
@ Gilles je ne comprends pas pourquoi vous prétendez cela. Comme .$HOME/.bashrcRich l'a montré ci-dessus, les paramètres de .bashrcseront disponibles dans les shells de connexion, et donc dans l'environnement de bureau. Par exemple, sur mon système Fedora, gnome-sessionest lancé en tant que -$SHELL -c gnome-session, ainsi, il .profileest lu.
Mikel
2
@PiotrDobrogost Oh, oui, la réponse de Rich pose un autre problème. L'inclusion de .bashrcdans .profilene fonctionne généralement pas, car elle .profilepeut être exécutée par /bin/shet non par bash (par exemple sous Ubuntu pour un login graphique par défaut), et ce shell peut ne pas être interactif (par exemple pour un login graphique).
Gilles
3
@Gilles re: "inclure .bashrc dans .profile" n’est pas du tout ce qui était recommandé (bien au contraire, en fait). Soit la réponse a été modifiée (cela ne semble pas être le cas), soit vos commentaires ne correspondent pas à ce qui est dit.
Michael
2
En général, +1, mais j'ajouterais à la recommandation la mention "court-circuit ... pour les shells non interactifs" ("près du sommet de .bashrc: [[ $- != *i* ]] && return"); J'aime que certaines de mes .bashrctâches soient exécutées même pour les shells non interactifs, en particulier pour définir env vars, lors de l'émission ssh hostname {command}, de sorte que les commandes distantes soient exécutées correctement (même si le shell n'est pas interactif). Mais les autres paramètres ultérieurs .bashrcdoivent être ignorés. Je vérifie habituellement si TERM = idiot et / ou non défini, puis je sors plus tôt.
Michael
18

Jetez un coup d'œil à cet excellent article de ShreevatsaR . Voici un extrait, mais consultez l'article du blog, qui inclut une explication de termes tels que "shell de connexion", un organigramme et un tableau similaire pour Zsh.

Pour Bash, ils fonctionnent comme suit. Lisez la colonne appropriée. Exécute A, puis B, puis C, etc. B1, B2, B3 signifie qu’il n’exécute que le premier des fichiers trouvés.

+----------------+-----------+-----------+------+
|                |Interactive|Interactive|Script|
|                |login      |non-login  |      |
+----------------+-----------+-----------+------+
|/etc/profile    |   A       |           |      |
+----------------+-----------+-----------+------+
|/etc/bash.bashrc|           |    A      |      |
+----------------+-----------+-----------+------+
|~/.bashrc       |           |    B      |      |
+----------------+-----------+-----------+------+
|~/.bash_profile |   B1      |           |      |
+----------------+-----------+-----------+------+
|~/.bash_login   |   B2      |           |      |
+----------------+-----------+-----------+------+
|~/.profile      |   B3      |           |      |
+----------------+-----------+-----------+------+
|BASH_ENV        |           |           |  A   |
+----------------+-----------+-----------+------+
|                |           |           |      |
+----------------+-----------+-----------+------+
|                |           |           |      |
+----------------+-----------+-----------+------+
|~/.bash_logout  |    C      |           |      |
+----------------+-----------+-----------+------+
Flimm
la source
Plutôt que d’afficher la même réponse sur plusieurs questions, il est préférable de l’adapter aux besoins spécifiques du demandeur. Si la réponse est exactement la même pour les deux questions, vous devriez poster une réponse unique et voter pour fermer les autres questions en duplicata de l'original.
Mokubai
1
@Mokubai L'autre question a déjà été marquée comme une copie de celle-ci.
Flimm
@ElipticalView: par set ne rien faire, vous parlez de la ligne: [ -z "$PS1" ] && return? Le tableau dans ma réponse donne la liste des scripts exécutés par Bash quel que soit le contenu des scripts. Si le script lui-même contient la ligne [ -z "$PS1" ] && return, cela prendrait effet, mais je ne pense pas que cela devrait signifier que je devrais changer le table.
Flimm
5

UN MEILLEUR COMMENTAIRE POUR LE CHEF OF / ETC / PROFILE

S'appuyant sur l'excellente réponse de Flimm ci-dessus, j'ai inséré ce nouveau commentaire à la tête de mon profil Debian / etc / (vous devrez peut-être l'adapter à votre distribution) :

# For BASH: Read down the appropriate column. Executes A, then B, then C, etc.
# The B1, B2, B3 means it executes only the first of those files found.  (A)
# or (B2) means it is normally sourced by (read by and included in) the
# primary file, in this case A or B2.
#
# +---------------------------------+-------+-----+------------+
# |                                 | Interactive | non-Inter. |
# +---------------------------------+-------+-----+------------+
# |                                 | login |    non-login     |
# +---------------------------------+-------+-----+------------+
# |                                 |       |     |            |
# |   ALL USERS:                    |       |     |            |
# +---------------------------------+-------+-----+------------+
# |BASH_ENV                         |       |     |     A      | not interactive or login
# |                                 |       |     |            |
# +---------------------------------+-------+-----+------------+
# |/etc/profile                     |   A   |     |            | set PATH & PS1, & call following:
# +---------------------------------+-------+-----+------------+
# |/etc/bash.bashrc                 |  (A)  |  A  |            | Better PS1 + command-not-found 
# +---------------------------------+-------+-----+------------+
# |/etc/profile.d/bash_completion.sh|  (A)  |     |            |
# +---------------------------------+-------+-----+------------+
# |/etc/profile.d/vte-2.91.sh       |  (A)  |     |            | Virt. Terminal Emulator
# |/etc/profile.d/vte.sh            |  (A)  |     |            |
# +---------------------------------+-------+-----+------------+
# |                                 |       |     |            |
# |   A SPECIFIC USER:              |       |     |            |
# +---------------------------------+-------+-----+------------+
# |~/.bash_profile    (bash only)   |   B1  |     |            | (doesn't currently exist) 
# +---------------------------------+-------+-----+------------+
# |~/.bash_login      (bash only)   |   B2  |     |            | (didn't exist) **
# +---------------------------------+-------+-----+------------+
# |~/.profile         (all shells)  |   B3  |     |            | (doesn't currently exist)
# +---------------------------------+-------+-----+------------+
# |~/.bashrc          (bash only)   |  (B2) |  B  |            | colorizes bash: su=red, other_users=green
# +---------------------------------+-------+-----+------------+
# |                                 |       |     |            |
# +---------------------------------+-------+-----+------------+
# |~/.bash_logout                   |    C  |     |            |
# +---------------------------------+-------+-----+------------+
#
# ** (sources !/.bashrc to colorize login, for when booting into non-gui)

Et cette note en tête de chacun des autres fichiers d'installation pour s'y référer:

# TIP: SEE TABLE in /etc/profile of BASH SETUP FILES AND THEIR LOAD SEQUENCE

À noter, je pense que le fichier / etc / profile de Debian par défaut (inclut) /etc/bash.bashrc (c’est à ce moment-là que /etc/bash.bashrc existe). Les scripts de connexion lisent donc les deux fichiers / etc, alors que les non-utilisateurs ne lisent que bash.bashrc.

A noter également que /etc/bash.bashrc est configuré pour ne rien faire s'il n'est pas exécuté de manière interactive. Ces deux fichiers ne sont donc que pour des scripts interactifs.

Vue elliptique
la source
4

La logique de configuration de bash elle-même n'est pas compliquée et expliquée dans d'autres réponses de cette page, sur serverfault et dans de nombreux blogs. Le problème, cependant, est ce que les distributions Linux font de bash , je veux dire la complexité et les différentes manières de configurer bash par défaut. http://mywiki.wooledge.org/DotFiles mentionne brièvement certaines de ces bizarreries. Voici un exemple de trace sur Fedora 29, qui indique quels fichiers sont sources, quel (s) autre (s) fichier (s) et dans quel ordre pour un scénario très simple: connexion à distance avec ssh puis démarrage d'un autre sous-shell:

ssh fedora29
 └─ -bash # login shell
      ├── /etc/profile
      |    ├─ /etc/profile.d/*.sh
      |    ├─ /etc/profile.d/sh.local
      |    └─ /etc/bashrc
      ├── ~/.bash_profile
      |    └─ ~/.bashrc
      |          └─ /etc/bashrc
      |
      |
      └─ $ bash  # non-login shell
            └─ ~/.bashrc
                 └─ /etc/bashrc
                       └─ /etc/profile.d/*.sh

La logique la plus complexe de Fedora est dans /etc/bashrc. Comme vu ci /etc/bashrc- dessus, un fichier que bash ne connaît pas elle-même, je veux dire, pas directement. Fedora /etc/bashrcvérifie si:

  • il provient d'un shell de connexion,
  • il est recherché par un shell interactif,
  • il a déjà été recherché

... et fait ensuite des choses complètement différentes selon celles-ci.

Si vous pensez pouvoir vous souvenir du graphique ci-dessus, c'est dommage, car ce n'est pas suffisant: ce graphique décrit simplement un scénario. Des choses légèrement différentes se produisent lorsque vous exécutez des scripts non interactifs ou démarrez une session graphique. J'ai omis ~/.profile. J'ai omis des bash_completionscripts. Pour des raisons de compatibilité ascendante, invoquer bash en tant que /bin/shau lieu de /bin/bashchanger son comportement. Qu'en est-il des zsh et autres coquillages? Et bien sûr, différentes distributions Linux font les choses différemment, par exemple Debian et Ubuntu sont livrés avec une version non standard de bas h, elle comporte des personnalisations spécifiques à Debian. Il cherche notamment un fichier inhabituel:/etc/bash.bashrc. Même si vous vous en tenez à une seule distribution Linux, celle-ci évoluera probablement avec le temps. Attendez: nous n’avons même pas touché macOS, FreeBSD, ... Enfin, pensons aux utilisateurs qui ont encore plus de créativité dans la manière dont leurs administrateurs ont configuré le système qu’ils doivent utiliser.

Comme en témoigne le flot incessant de discussions sur ce sujet, c'est une cause perdue. Tant que vous voulez juste ajouter de nouvelles valeurs, quelques "essais et erreurs" ont tendance à suffire. Le vrai plaisir commence lorsque vous souhaitez modifier dans un fichier (utilisateur) quelque chose déjà défini dans un autre (dans / etc). Alors soyez prêt à passer du temps à concevoir une solution qui ne sera jamais portable.

Pour vous amuser un peu, voici le "graphique source" du même scénario simple sur Clear Linux à compter de juin 2019:

ssh clearlinux
 └─ -bash # login shell
      ├── /usr/share/defaults/etc/profile
      |    ├─ /usr/share/defaults/etc/profile.d/*
      |    ├─ /etc/profile.d/*
      |    └─ /etc/profile
      ├── ~/.bash_profile
      |
      |
      └─  $ bash   # non-login shell
           ├─ /usr/share/defaults/etc/bash.bashrc
           |      ├─ /usr/share/defaults/etc/profile
           |      |    ├─ /usr/share/defaults/etc/profile.d/*
           |      |    ├─ /etc/profile.d/*
           |      |    └─ /etc/profile
           |      └─ /etc/profile
           └─ ~/.bashrc
Mars
la source