Diferencia entre .bashrc y .bash_profile

449

¿Cuál es la diferencia entre .bashrcy .bash_profiley cuál debería usar?

cfischer
fuente
2
Consulte también esta pregunta similar en ubuntu.stackexchange.com/questions/1528/bashrc-or-bash-profile
Stefan Lasiewski el
Si desea una explicación más completa que también implique .profile, eche un vistazo a esta pregunta: superuser.com/questions/789448/…
Flimm
Esta respuesta también cubre algunos aspectos stackoverflow.com/questions/415403/…
Sergey Voronezhskiy

Respuestas:

517

Tradicionalmente, cuando inicia sesión en un sistema Unix, el sistema iniciaría un programa para usted. Ese programa es un shell, es decir, un programa diseñado para iniciar otros programas. Es un shell de línea de comando: inicia otro programa escribiendo su nombre. El shell predeterminado, un shell Bourne, lee los comandos ~/.profilecuando se invoca como el shell de inicio de sesión.

Bash es un caparazón tipo Bourne. Lee los comandos de ~/.bash_profilecuando se invoca como el shell de inicio de sesión, y si ese archivo no existe¹, intenta leer en su ~/.profilelugar.

Puede invocar un shell directamente en cualquier momento, por ejemplo, iniciando un emulador de terminal dentro de un entorno GUI. Si el shell no es un shell de inicio de sesión, no se lee ~/.profile. Cuando comienza bash como un shell interactivo (es decir, no para ejecutar un script), se lee ~/.bashrc(excepto cuando se invoca como un shell de inicio de sesión, luego solo se lee ~/.bash_profileo ~/.profile.

Por lo tanto:

  • ~/.profile es el lugar para colocar cosas que se aplican a toda su sesión, como los programas que desea iniciar cuando inicia sesión (pero no los programas gráficos, van a un archivo diferente) y las definiciones de variables de entorno.

  • ~/.bashrces el lugar para colocar cosas que se aplican solo a bash en sí, como alias y definiciones de funciones, opciones de shell y configuraciones de solicitud. (También puedes poner atajos de teclado allí, pero para bash normalmente entran ~/.inputrc).

  • ~/.bash_profilese puede usar en lugar de ~/.profile, pero se lee solo por bash, no por cualquier otro shell. (Esto es principalmente una preocupación si desea que sus archivos de inicialización funcionen en varias máquinas y su shell de inicio de sesión no es un bash en todas ellas). Este es un lugar lógico para incluir ~/.bashrcsi el shell es interactivo. Recomiendo los siguientes contenidos en ~/.bash_profile:

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

En unidades modernas, hay una complicación adicional relacionada con ~/.profile. Si inicia sesión en un entorno gráfico (es decir, si el programa donde escribe su contraseña se ejecuta en modo gráfico), no obtendrá automáticamente un shell de inicio de sesión que lea ~/.profile. Dependiendo del programa de inicio de sesión gráfico, del administrador de ventanas o del entorno de escritorio que ejecute después, y de cómo su distribución configuró estos programas, su ~/.profilelectura puede o no ser leída. Si no es así, generalmente hay otro lugar donde puede definir variables de entorno y programas para iniciar cuando inicia sesión, pero desafortunadamente no hay una ubicación estándar.

Tenga en cuenta que puede ver recomendaciones aquí y allá para colocar definiciones de variables de entorno ~/.bashrco siempre iniciar shells de inicio de sesión en terminales. Ambas son malas ideas. El problema más común con cualquiera de estas ideas es que las variables de entorno solo se establecerán en programas iniciados a través del terminal, no en programas que se inicien directamente con un ícono o menú o método abreviado de teclado.

¹ Para completar, por solicitud: si .bash_profileno existe, bash también lo intenta .bash_loginantes de recurrir a .profile. Siéntase libre de olvidar que existe.

Gilles
fuente
11
+1 para una buena publicación. TAMBIÉN gracias por agregar la sección sobre "inicio de sesión gráfico vs shell de inicio de sesión" ... Tuve el problema donde pensé que ~ / .profile SIEMPRE se ejecutaría para gráfico / shell ... pero no se ejecuta cuando el usuario inicia sesión a través de inicio de sesión gráfico. Gracias por resolver ese misterio.
Trevor Boyd Smith
44
@Gilles: ¿Podría explicar con más detalle, con ejemplos, por qué ejecutar un shell de inicio de sesión en cada terminal es una mala idea? ¿Es esto solo un problema con el escritorio de Linux? (Supongo que en OS X Terminal se ejecuta un shell de inicio de sesión cada vez, y nunca he notado ningún efecto secundario (aunque generalmente uso iTerm). Pero no puedo pensar en muchas variables de entorno que me interesarían fuera de un terminal. (¿Quizás HTTP_PROXY?))
iconoclasta
2
@Brandon Si ejecuta un shell de inicio de sesión en cada terminal, eso anulará las variables de entorno proporcionadas por el entorno. En situaciones cotidianas, puede salirse con la suya, pero vendrá y lo morderá tarde o temprano, cuando desee configurar diferentes variables en un terminal (por ejemplo, para probar una versión diferente de un programa): ejecutar un el shell de inicio de sesión anularía su configuración local.
Gilles
44
La declaración ~/.bash_profilese puede usar en lugar de ~/.profile, pero también debe incluir ~/.bashrcsi el shell es interactivo. es engañoso ya que estos son problemas ortogonales. No importa si usa ~/.bash_profileo ~/.profiletiene que incluir ~/.bashrcen el que usa si desea que la configuración desde allí tenga efecto en el shell de inicio de sesión.
Piotr Dobrogost
3
@Gilles Claro, pero la forma en que se formula la oración en la respuesta sugiere que la necesidad de incluir ~/.bashrctiene algo que ver con elegir en ~/.bash_profilelugar de lo ~/.profilecual no es cierto. Si alguien incluye ~/.bashrcalgún tipo de script que se obtiene en el momento del inicio de sesión (aquí es ~/.bash_profileo ~/.profile) es porque quiere que la configuración ~/.bashrcse aplique al shell de inicio de sesión de la misma manera que se aplica a un shell sin inicio de sesión.
Piotr Dobrogost
53

De este breve artículo

Según la página de manual de bash, .bash_profile se ejecuta para shells de inicio de sesión, mientras que .bashrc se ejecuta para shells interactivos sin inicio de sesión.

¿Qué es un shell de inicio o no inicio de sesión?

Cuando inicia sesión (por ejemplo: escriba nombre de usuario y contraseña) a través de la consola, ya sea físicamente sentado en la máquina al arrancar, o de forma remota a través de ssh: .bash_profile se ejecuta para configurar las cosas antes del símbolo del sistema inicial.

Pero, si ya ha iniciado sesión en su máquina y abre una nueva ventana de terminal (xterm) dentro de Gnome o KDE, entonces .bashrc se ejecuta antes del símbolo del sistema de la ventana. .bashrc también se ejecuta cuando inicia una nueva instancia de bash escribiendo / bin / bash en un terminal.

Jarvin
fuente
12
Ligeras actualizaciones: 'Ejecutado' es probablemente un término ligeramente engañoso, ambos son de origen. Los sonidos ejecutados parecen ejecutarse como un script, fork / exec yadda yadda. Se ejecuta en el contexto del shell actual. Más importante aún, .bashrc se ejecuta con mucha más frecuencia. Se ejecuta en cada ejecución de script bash, y también si no tiene un .bash_profile. Además, dependiendo de cómo configure sus xterms, puede crear un shell que obtenga .bash_profile
Rich Homolka
36

En los viejos tiempos, cuando los pseudo tty no eran pseudo y realmente, bueno, mecanografiados, y los módems accedían a UNIX tan lento que podía ver cada letra impresa en su pantalla, la eficiencia era primordial. Para ayudar a la eficiencia, tenía un concepto de una ventana de inicio de sesión principal y cualquier otra ventana que realmente funcionara. En su ventana principal, le gustaría recibir notificaciones a cualquier correo nuevo, posiblemente ejecutar algunos otros programas en segundo plano.

Para respaldar esto, los shells obtuvieron un archivo .profileespecíficamente en 'shells de inicio de sesión'. Esto haría lo especial, una vez que se configura la sesión. Bash extendió esto un poco para mirar .bash_profile primero antes de .profile, de esta manera podría poner bash solo cosas allí (para que no arruinen el shell Bourne, etc., que también miró .profile). Otros shells, sin inicio de sesión, solo generarían el archivo rc, .bashrc (o .kshrc, etc.).

Esto es un poco anacrónico ahora. No inicia sesión en un shell principal tanto como inicia sesión en un administrador de ventanas GUI. No hay una ventana principal diferente a cualquier otra ventana.

Mi sugerencia: no se preocupe por esta diferencia, se basa en un estilo anterior de uso de Unix. Elimina la diferencia en tus archivos. El contenido completo de .bash_profile debe ser:

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

Y ponga todo lo que realmente desea configurar en .bashrc

Recuerde que .bashrc se obtiene de todos los shells, interactivos y no interactivos. Puede cortocircuitar el abastecimiento de shells no interactivos colocando este código cerca de la parte superior de .bashrc:

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

Rich Homolka
fuente
66
Esta es una mala idea, mira mi respuesta . En particular, las variables de entorno solo se establecerán en programas iniciados a través del terminal, no en programas iniciados directamente con un icono o menú o método abreviado de teclado.
Gilles
44
@Gilles No entiendo por qué reclamas esto. Como .$HOME/.bashrcRich mostró anteriormente, la configuración .bashrcestará disponible en shells de inicio de sesión y, por lo tanto, también en el entorno de escritorio. Por ejemplo, en mi sistema Fedora, gnome-sessionse inicia como -$SHELL -c gnome-session, por lo que .profilese lee.
Mikel
2
@PiotrDobrogost Oh, sí, hay otro problema con la respuesta de Rich. Por lo general, incluir .bashrcen .profileno funciona, porque .profilepuede ejecutarse /bin/shy no bash (por ejemplo, en Ubuntu para un inicio de sesión gráfico de forma predeterminada), y ese shell puede no ser interactivo (por ejemplo, para un inicio de sesión gráfico).
Gilles
3
@Gilles re: "incluir .bashrc en .profile" no es lo que se recomendó (al contrario, de hecho). O bien la respuesta fue editada (no parece ser así), o sus comentarios no se alinean con lo que se dice.
michael
2
En general, +1, pero agregaría a la recomendación "cortocircuito ... para shells no interactivos" ("cerca de la parte superior de .bashrc: [[ $- != *i* ]] && return"); Me gusta que algunos de mis .bashrcse ejecuten incluso para shells no interactivos, específicamente para establecer env vars, cuando se emiten ssh hostname {command}, para que los comandos remotos se ejecuten correctamente (aunque el shell no sea interactivo). Pero otras configuraciones posteriores .bashrcdeben ser ignoradas. Por lo general, verifico para TERM = tonto y / o sin ajustar, y luego salgo temprano.
michael
18

Echa un vistazo a esta excelente publicación de blog de ShreevatsaR . Aquí hay un extracto, pero vaya a la publicación del blog, incluye una explicación de términos como "shell de inicio de sesión", un diagrama de flujo y una tabla similar para Zsh.

Para Bash, funcionan de la siguiente manera. Lea la columna apropiada. Ejecuta A, luego B, luego C, etc. El B1, B2, B3 significa que ejecuta solo el primero de los archivos encontrados.

+----------------+-----------+-----------+------+
|                |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
fuente
En lugar de publicar la misma respuesta en múltiples preguntas, se prefiere si puede adaptar su respuesta a las necesidades específicas del autor de la pregunta. Si la respuesta es exactamente la misma para ambas preguntas, entonces debe publicar una sola respuesta y votar para cerrar las otras preguntas como duplicados del original.
Mokubai
1
@Mokubai La otra pregunta ya ha sido marcada como un duplicado de esta.
Flimm
@ElipticalView: configurado para no hacer nada, te estás refiriendo a la línea [ -z "$PS1" ] && return:? La tabla en mi respuesta está dando la lista de scripts ejecutados por Bash, independientemente del contenido de los scripts, si el script en sí tiene la línea [ -z "$PS1" ] && return, por supuesto que tendría efecto, pero no creo que eso deba significar que debería cambiar el mesa.
Flimm
5

UN MEJOR COMENTARIO PARA EL JEFE DE / ETC / PERFIL

Sobre la base de la excelente respuesta de Flimm anterior, inserté este nuevo comentario en la cabeza de mi perfil de Debian / etc / (es posible que deba ajustarlo para su distribución) :

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

Y esta nota al principio de cada uno de los otros archivos de configuración para referirse a ella:

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

Vale la pena señalar que creo que es el perfil / etc / de Debian por defecto (incluye) /etc/bash.bashrc (ahí es cuando existe /etc/bash.bashrc). Por lo tanto, los scripts de inicio de sesión leen ambos archivos / etc, mientras que los que no lo hacen solo bash.bashrc.

También cabe destacar que /etc/bash.bashrc está configurado para no hacer nada cuando no se ejecuta de forma interactiva. Entonces, estos dos archivos son solo para scripts interactivos.

Vista elíptica
fuente
4

La lógica de configuración de bash en sí no es una locura complicada y se explica en otras respuestas en esta página, en serverfault y en muchos blogs. Sin embargo, el problema es lo que las distribuciones de Linux hacen de bash , me refiero a las complejas y diversas formas en que configuran bash de forma predeterminada. http://mywiki.wooledge.org/DotFiles menciona brevemente algunas de estas peculiaridades. Aquí hay una traza de muestra en Fedora 29, que muestra qué archivos se originan, qué otros archivos y en qué orden para un escenario muy simple: conectarse de forma remota con ssh y luego iniciar otra subshell:

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 lógica más compleja de Fedora está en /etc/bashrc. Como se ve arriba, /etc/bashrces un archivo que Bash no conoce, es decir, no directamente. Fedora /etc/bashrcprueba si:

  • proviene de un shell de inicio de sesión,
  • está siendo generado por un shell interactivo,
  • ya ha sido obtenido

... y luego hace cosas completamente diferentes dependiendo de eso.

Si cree que puede recordar el gráfico anterior, entonces es una lástima porque no es suficiente: este gráfico simplemente describe un solo escenario, suceden cosas ligeramente diferentes cuando se ejecutan scripts no interactivos o se inicia una sesión gráfica. He omitido ~/.profile. He omitido bash_completionguiones. Por razones de compatibilidad con versiones anteriores, invocar bash como en /bin/shlugar de /bin/bashcambiar su comportamiento. ¿Qué pasa con zsh y otras conchas? Y, por supuesto, las diferentes distribuciones de Linux hacen las cosas de manera diferente, por ejemplo, Debian y Ubuntu vienen con una versión no estándar de bas h, tiene personalizaciones específicas de Debian. En particular, busca un archivo inusual:/etc/bash.bashrc. Incluso si se atiene a una única distribución de Linux, probablemente evolucione con el tiempo. Espere: ni siquiera hemos tocado macOS, FreeBSD, ... Finalmente, pensemos en los usuarios que se quedan con las formas aún más creativas que sus administradores han configurado el sistema que tienen que usar.

Como lo demuestra el flujo interminable de discusiones sobre este tema, es una causa perdida. Mientras solo desee agregar nuevos valores, algunos "prueba y error" tienden a ser suficientes. La verdadera diversión comienza cuando desea modificar en un archivo (usuario) algo ya definido en otro (en / etc). Entonces prepárese para pasar un tiempo diseñando una solución que nunca será portátil.

Para divertirse un poco más, aquí está el "gráfico fuente" para el mismo escenario simple en Clear Linux a partir de junio de 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
Marzo
fuente