En Linux y, que yo sepa, en todos los sistemas Unix, los emuladores de terminal ejecutan shells interactivos sin inicio de sesión de forma predeterminada. Esto significa que, para bash, el shell iniciado:
Cuando se inicia un shell interactivo que no es un shell de inicio de sesión, bash lee y ejecuta comandos desde /etc/bash.bashrc
y ~/.bashrc
, si estos archivos existen. Esto se puede inhibir usando el --norc
opción.
El --rcfile
La opción de archivo obligará a bash a leer y ejecutar comandos desde el archivo en lugar de /etc/bash.bashrc
y ~/.bashrc
.
Y para shells de inicio de sesión:
Cuando bash se invoca como un shell de inicio de sesión interactivo, o como un shell no interactivo con --login
opción, primero lee y ejecuta comandos desde el archivo /etc/profile
, si ese archivo existe. Después de leer ese archivo, busca ~/.bash_profile
, ~/.bash_login
y ~/.profile
, en ese orden, y lee y ejecuta comandos desde el primero que existe y es legible.
El --noprofile
La opción se puede usar cuando se inicia el shell para inhibir este comportamiento.
En OSX, sin embargo, el shell predeterminado (que es bash) se inició en la terminal predeterminada (Terminal.app) en realidad genera ~/.bash_profile
o ~.profile
etc. En otras palabras, actúa como un shell de inicio de sesión.
Pregunta principal :¿Por qué el shell interactivo predeterminado es un shell de inicio de sesión en OSX? ¿Por qué OSX eligió hacer esto? Esto significa que todas las instrucciones/tutoriales para cosas basadas en shell que mencionan cambios en ~/.bashrc
fallará en OSX o viceversa para ~/.profile
. Aún así, aunque se pueden hacer muchas acusaciones contra Apple, contratar desarrolladores incompetentes o idiotas no es una de ellas. Presumiblemente, tenían una buena razón para esto, así que ¿por qué?
Subpreguntas:¿Terminal.app realmente ejecuta un shell de inicio de sesión interactivo o han cambiado el comportamiento de bash? ¿Es esto específico de Terminal.app o es independiente del emulador de terminal?
Respuesta aceptada:
La forma en que se supone el trabajo es que, en el momento en que obtiene un indicador de shell, tanto .profile
y .bashrc
han sido ejecutados. Los detalles específicos de cómo llegó a ese punto son de relevancia secundaria, pero si alguno de los archivos no se ejecuta en absoluto, tendría un shell con configuraciones incompletas.
La razón por la que los emuladores de terminal en Linux (y otros sistemas basados en X) no necesitan para ejecutar .profile
en sí mismos es que normalmente ya se habrá ejecutado cuando inició sesión en X. La configuración en .profile
se supone que son del tipo que pueden ser heredados por los subprocesos, siempre que se ejecute una vez cuando inicie sesión (por ejemplo, a través de .Xsession
), no es necesario volver a ejecutar otras subcapas.
Como explica la página wiki de Debian enlazada por Alan Shutko:
“¿Por qué .bashrc
un archivo separado de .bash_profile
, ¿entonces? Esto se hace principalmente por razones históricas, cuando las máquinas eran extremadamente lentas en comparación con las estaciones de trabajo actuales. Procesando los comandos en .profile
o .bash_profile
podría tomar bastante tiempo, especialmente en una máquina donde gran parte del trabajo tenía que ser realizado por comandos externos (pre-bash). Por lo tanto, los difíciles comandos de configuración inicial, que crean variables de entorno que se pueden pasar a los procesos secundarios, se colocan en .bash_profile
. Las configuraciones transitorias y los alias que no se heredan se colocan en .bashrc
para que puedan ser releídos por cada subshell.”
Las mismas reglas también se aplican a OSX, excepto por una cosa:la GUI de OSX no ejecuta .profile
cuando inicia sesión, aparentemente porque tiene su propio método para cargar la configuración global. Pero eso significa que un emulador de terminal en OSX sí necesita ejecutar .profile
(diciéndole al shell que se inicia que es un shell de inicio de sesión), de lo contrario, terminaría con un shell potencialmente dañado.
Ahora, una especie de peculiaridad tonta de bash, no compartida por la mayoría de los otros shells, es que no ejecutará automáticamente .bashrc
si se inició como un shell de inicio de sesión. La solución estándar para eso es incluir algo como los siguientes comandos en .bash_profile
:
[[ -e ~/.profile ]] && source ~/.profile # load generic profile settings
[[ -e ~/.bashrc ]] && source ~/.bashrc # load aliases etc.
Alternativamente, es posible no tener .bash_profile
en absoluto, y simplemente incluya un código específico de bash en el .profile
genérico archivo para ejecutar .bashrc
si es necesario.
Si el .bash_profile
predeterminado de OSX o .profile
no hacer esto, entonces podría decirse que es un error. En cualquier caso, la solución adecuada es simplemente agregar esas líneas a .bash_profile
.
Editar: Como señala strugee, el shell predeterminado en OSX solía ser tcsh, cuyo comportamiento es mucho más sensato a este respecto:cuando se ejecuta como un shell de inicio de sesión interactivo, tcsh lee automáticamente tanto .profile
y .tcshrc
/ .cshrc
y, por lo tanto, no necesita soluciones alternativas como .bash_profile
truco que se muestra arriba.
Basado en esto, estoy 99% seguro de que la falla de OSX para proporcionar un .bash_profile
predeterminado apropiado es porque, cuando cambiaron de tcsh a bash, la gente de Apple simplemente no notó esta pequeña verruga en el comportamiento de inicio de bash. Con tcsh, no se necesitaban tales trucos:iniciar tcsh como un shell de inicio de sesión desde un emulador de terminal OSX Just Plain Works y hace lo correcto sin tales errores.