Sous Linux et, à ma connaissance, tous les systèmes Unix, les émulateurs de terminaux exécutent par défaut des shells interactifs sans connexion. Cela signifie que, pour bash, le shell démarré :
Lorsqu'un shell interactif qui n'est pas un shell de connexion est démarré, bash lit et exécute les commandes de
/etc/bash.bashrc
et~/.bashrc
, si ces fichiers existent. Cela peut être inhibé en utilisant le--norc
option.Le
--rcfile
L'option file forcera bash à lire et à exécuter les commandes du fichier au lieu de/etc/bash.bashrc
et~/.bashrc
.
Et pour les shells de connexion :
Lorsque bash est appelé en tant que shell de connexion interactif ou en tant que shell non interactif avec le
--login
option, il lit et exécute d'abord les commandes du fichier/etc/profile
, si ce fichier existe. Après avoir lu ce fichier, il recherche~/.bash_profile
,~/.bash_login
, et~/.profile
, dans cet ordre, et lit et exécute les commandes à partir de la première qui existe et est lisible.Le
--noprofile
L'option peut être utilisée au démarrage du shell pour inhiber ce comportement.
Sur OSX, cependant, le shell par défaut (qui est bash) démarré dans le terminal par défaut (Terminal.app) source en fait ~/.bash_profile
ou ~.profile
etc. En d'autres termes, il agit comme un shell de connexion.
Question principale :Pourquoi le shell interactif par défaut est-il un shell de connexion sous OSX ? Pourquoi OSX a-t-il choisi de faire cela ? Cela signifie que toutes les instructions/tutoriels pour les choses basées sur le shell qui mentionnent de changer les choses dans ~/.bashrc
échouera sur OSX ou vice versa pour ~/.profile
. Pourtant, bien que de nombreuses accusations puissent être portées contre Apple, l'embauche de développeurs incompétents ou idiots n'en fait pas partie. Vraisemblablement, ils avaient une bonne raison pour cela, alors pourquoi ?
Sous-questions :Terminal.app exécute-t-il réellement un shell de connexion interactif ou a-t-il modifié le comportement de bash ? Est-ce spécifique à Terminal.app ou est-ce indépendant de l'émulateur de terminal ?
Réponse acceptée :
La façon dont c'est supposé le travail est que, au moment où vous obtenez une invite du shell, à la fois .profile
et .bashrc
ont été exécutés. Les détails spécifiques de la façon dont vous arrivez à ce point sont d'importance secondaire, mais si l'un des fichiers n'était pas exécuté du tout, vous auriez un shell avec des paramètres incomplets.
La raison pour laquelle les émulateurs de terminaux sous Linux (et d'autres systèmes basés sur X) n'ont pas besoin pour exécuter .profile
eux-mêmes est qu'il aura normalement déjà été exécuté lorsque vous vous êtes connecté à X. Les paramètres dans .profile
sont censés être du type qui peut être hérité par les sous-processus, donc tant qu'il est exécuté une fois lorsque vous vous connectez (par exemple via .Xsession
), les autres sous-shells n'ont pas besoin de le relancer.
Comme l'explique la page wiki Debian liée par Alan Shutko :
"Pourquoi
.bashrc
un fichier séparé de.bash_profile
, alors? Cela se fait principalement pour des raisons historiques, lorsque les machines étaient extrêmement lentes par rapport aux postes de travail actuels. Traitement des commandes dans.profile
ou.bash_profile
pouvait prendre beaucoup de temps, surtout sur une machine où une grande partie du travail devait être effectuée par des commandes externes (pre-bash). Ainsi, les commandes de configuration initiales difficiles, qui créent des variables d'environnement pouvant être transmises aux processus enfants, sont placées dans.bash_profile
. Les paramètres transitoires et les alias qui ne sont pas hérités sont placés dans.bashrc
afin qu'ils puissent être relus par chaque sous-shell.”
Toutes les mêmes règles s'appliquent également à OSX, à une exception près :l'interface graphique OSX n'exécute pas .profile
lorsque vous vous connectez, apparemment parce qu'il a sa propre méthode de chargement des paramètres globaux. Mais cela signifie qu'un émulateur de terminal sur OSX fait besoin d'exécuter .profile
(en disant au shell qu'il lance qu'il s'agit d'un shell de connexion), sinon vous vous retrouveriez avec un shell potentiellement paralysé.
Maintenant, une sorte de particularité idiote de bash, non partagée par la plupart des autres shells, est qu'il n'exécutera pas automatiquement .bashrc
s'il est démarré en tant que shell de connexion. La solution standard pour cela consiste à inclure quelque chose comme les commandes suivantes dans .bash_profile
:
[[ -e ~/.profile ]] && source ~/.profile # load generic profile settings
[[ -e ~/.bashrc ]] && source ~/.bashrc # load aliases etc.
Alternativement, il est possible de ne pas avoir de .bash_profile
du tout, et incluez simplement du code spécifique à bash dans le générique .profile
fichier pour exécuter .bashrc
si nécessaire.
Si la valeur par défaut d'OSX .bash_profile
ou .profile
pas faites cela, alors c'est sans doute un bug. Dans tous les cas, la solution de contournement appropriée consiste simplement à ajouter ces lignes à .bash_profile
.
Modifier : Comme le note strugee, le shell par défaut sur OSX était tcsh, dont le comportement est beaucoup plus sain à cet égard :lorsqu'il est exécuté en tant que shell de connexion interactif, tcsh lit automatiquement à la fois .profile
et .tcshrc
/ .cshrc
, et n'a donc pas besoin de solutions de contournement comme le .bash_profile
astuce ci-dessus.
Sur cette base, je suis sûr à 99 % que l'échec d'OSX à fournir un .bash_profile
par défaut approprié est parce que, lorsqu'ils sont passés de tcsh à bash, les gens d'Apple n'ont tout simplement pas remarqué cette petite verrue dans le comportement de démarrage de bash. Avec tcsh, aucune astuce de ce type n'était nécessaire - démarrer tcsh en tant que shell de connexion à partir d'un émulateur de terminal OSX Just Plain Works et fait ce qu'il faut sans de tels klugs.