Elegir entre .bashrc, .profile, .bash_profile, etc. [duplicado]

197

Esta pregunta ya tiene una respuesta aquí:

Esto es embarazoso, pero después de muchos años de uso de sistemas POSIX tiempo completo, todavía tienen un tiempo difícil averiguar si una personalización de la cáscara debe ir en .bashrc, .profileo en otro lugar. Sin mencionar algunos de los archivos de configuración específicos del sistema operativo como .pam_environment.

Sí, sé cómo descifrar la documentación y saber cuándo se carga o no cada archivo. Lo que me pregunto es si alguien ha reunido todas las pautas integrales sobre cómo decidir en qué archivo colocar un tipo determinado de personalización.

Avdi
fuente
66
esta pregunta no debe marcarse como duplicada, la razón es que .profile no está disponible en la pregunta agregada.
Premraj
Respuesta: serverfault.com/q/261802/270464
Premraj

Respuestas:

222

TL; DR:

  • ~/.bash_profiledebe ser súper simple y solo cargar .profiley .bashrc(en ese orden)

  • ~/.profiletiene cosas que NO están específicamente relacionadas con bash, como variables de entorno ( PATHy amigos)

  • ~/.bashrctiene todo lo que quieras en una línea de comandos interactiva. Símbolo del sistema, EDITORvariable, bash alias para mi uso

Algunas otras notas:

  • Cualquier cosa que deba estar disponible para aplicaciones gráficas O para sh (o bash invocado como sh) DEBE estar en~/.profile

  • ~/.bashrc no debe dar salida a nada

  • Todo lo que debe estar disponible solo para iniciar sesión en shells debe ir ~/.profile

  • Asegúrese de que ~/.bash_loginno exista.

Dan Rabinowitz
fuente
3
+1, esto permite ~/.profileestablecer correctamente el entorno para servicios como GDM / LightDM / LXDM que ejecutan explícitamente / bin / sh.
Grawity
12
Mis .bashrcresultados son muchas cosas, ¿puedes comentar sobre eso? En particular, ¿dónde debo poner la salida de saludo?
Calimo
14
@Calimo: haz que solo muestre cosas en modo interactivo. Puede probarlo usando [[ $- == *i* ]], es decir, buscando 'i' en la $-variable especial . Por supuesto, solo importa en primer lugar en los sistemas donde bash se compila para leer .bashrcen modo no interactivo. (Es decir, Debian, pero no Arch.) Pero es una causa frecuente de misteriosos mensajes de error cuando intenta conectarse utilizando sftpo scpo herramientas similares.
Grawity
44
Ahora tengo que saber, ¿por qué no debería existir .bash_login? ¿Qué hace?
tedder42
11
@ tedder42: hace lo mismo que .bash_profiley .profile. Pero bash solo lee el primero de cada tres. Es decir, si tiene una .bash_login, entonces ambos .profiley .bash_profileserá misteriosamente ignorado.
Grawity
54

En los últimos años, he tenido mucho tiempo que perder, así que he investigado esto durante un poco más de solo 10 minutos. No tengo idea si este es el mejor diseño, es solo uno que funciona correctamente en casi todos los casos.

Los requisitos:

  • ~/.profile debe ser compatible con cualquier / bin / sh: esto incluye bash, dash, ksh, cualquier otra cosa que una distribución pueda elegir usar.

  • Las variables de entorno deben colocarse en un archivo que sea leído por los inicios de sesión de la consola (es decir, un shell de 'inicio de sesión') y los inicios de sesión gráficos (es decir, administradores de pantallas como GDM, LightDM o LXDM).

  • No tiene mucho sentido tener ambos ~/.profile y ~/.bash_profile. Si falta el último, bash usará felizmente el primero, y cualquier línea específica de bash puede protegerse con un cheque para $BASHo $BASH_VERSION.

  • La separación entre *profiley *rces que el primero se usa para shells de 'inicio de sesión', y el segundo cada vez que abre una ventana de terminal. Sin embargo, bash en el modo de 'inicio de sesión' no tiene origen ~/.bashrc, por lo tanto, ~/.profiledebe hacerlo manualmente.

La configuración más simple sería:

  • Tenga un ~/.profileque establezca todas las variables de entorno (excepto las específicas de bash), tal vez imprima una o dos líneas, luego las fuentes ~/.bashrcsi se ejecuta con bash, de lo contrario se adhiere a la sintaxis compatible con sh.

    export TZ = "Europa / París"
    export EDITOR = "vim"
    si ["$ BASH"]; entonces
        . ~ / .bashrc
    fi
    tiempo de actividad
    
  • Tenga un ~/.bashrcdispositivo que realice cualquier configuración específica de shell, guardado con una comprobación de modo interactivo para evitar romper cosas como sftpen Debian (donde bash se compila con la opción de cargar ~/.bashrcincluso para shells no interactivos):

    [[$ - == * i *]] || volver 0
    
    PS1 = '\ h \ w \ $'
    
    start () {sudo service "$ 1" start; }
    

Sin embargo, también existe el problema de que ciertos comandos no interactivos (por ejemplo ssh <host> ls) se saltan ~/.profile, pero las variables de entorno serían muy útiles para ellos.

  • Ciertas distribuciones (por ejemplo, Debian) compilan su bash con la opción de obtener ~/.bashrcdichos inicios de sesión no interactivos. En este caso, he encontrado útil mover todas las variables de entorno (las export ...líneas) a un archivo separado ~/.environ, y obtenerlo de ambos .profile y .bashrc, con una protección para evitar hacerlo dos veces:

    Si ! ["$ PREFIJO"]; a continuación,    # o $ EDITOR, o $ TZ, o ... 
        . ~ / .environ            # generalmente cualquier variable que .environ configuraría
    fi
    
  • Desafortunadamente, para otras distribuciones (por ejemplo, Arch), no he encontrado una solución muy buena. Una posibilidad es usar el módulo PAM pam_env (habilitado por defecto), colocando lo siguiente en ~/.pam_environment:

    BASH_ENV =. /. Environmental         # no es un error tipográfico; tiene que ser un camino, pero ~ no funcionará
    

    Luego, por supuesto, actualizando ~/.environa unset BASH_ENV.


¿Conclusión? Las conchas son un dolor. Las variables de entorno son un dolor. Las opciones de tiempo de compilación específicas de la distribución son un dolor inmenso en el culo.

Gravedad
fuente
2
1 para el último párrafo, pero prefiero abastecimiento .profiley .bashrcde .bash_profiley mantener .profilelimpio.
nyuszika7h
@ nyuszika7h: Mi .profile está limpio , gracias.
Grawity
1
Tenga en cuenta que el comentario re cada vez que abre una ventana es al revés para OSX
Mark
1
"No tiene mucho sentido tener ambos ~/.profiley ~/.bash_profile": no estoy de acuerdo. Vea la respuesta de Dan para saber por qué.
rubenvb
@rubenvb ¿Puede citar la parte relevante? Creo que está bien tener solo una .profiley proteger las bashpartes específicas con condicionales.
Kelvin
36

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
Esto es bonito. Es importante tener en cuenta que generalmente las /etc/profilellamadas /etc/bash.bashrcy las ~/.profilellamadas ~.bashrc. De manera efectiva, /etc/bash.bashrcy también ~/.bashrcse están ejecutando para inicios de sesión interactivos.
wisbucky
Tenga en cuenta que algunas distribuciones parecen anular este esquema (con extrañas consecuencias); consulte, por ejemplo, mi informe de errores para opensuse aquí: bugzilla.opensuse.org/show_bug.cgi?id=1078124
Christian Herenz
Por cierto. al menos con bash, ninguno de esos archivos se está ejecutando cuando se llama a bash a través de/bin/sh
JepZ
@JepZ Tienes razón, eso es lo que explica la tercera columna "Script".
Flimm
1
@Flimm Bueno, la columna 'Script' describe lo que sucede cuando inicia un script no interactivo a través de bash (por ejemplo, / bin / bash). Sin embargo, si inicia un script a través de sh (y / bin / sh es un enlace simbólico a / bin / bash), nada de lo anterior se ejecuta (ni siquiera BASH_ENV). El párrafo relacionado de la página de manual de bash se puede encontrar buscando If bash is invoked with the name sh.
JepZ
21

Te ofrezco mis pautas "integrales":

  • Haga .bash_profiley .profilecargue .bashrcsi existe, por ejemplo, utilizando [ -r $HOME/.bashrc ] && source $HOME/.bashrc
  • Pon todo lo demás adentro .bashrc.
  • Deja de preocuparte.
  • Cada cuatro años más o menos, dedique diez minutos a investigar esta misma pregunta antes de darse por vencido y volver a "no preocuparse".

EDITAR: Se agregaron citas de miedo a "integral" por si alguien se siente tentado a creerlo. ;)

Pez mecánico
fuente
3
Tener ambos .bash_profiley .profilees un poco redundante; solo necesitas lo último. Sin embargo, debe hacerlo a prueba / bin / sh: if [ "$BASH" ] && [ -r ~/.bashrc ]; then . ~/.bashrc; fiya que hay programas (a saber, gdm / lightdm) que obtienen el archivo manualmente de un script / bin / sh. Esto también significa que el entorno mantenido .bashrcsería ineficaz. Tuve que -1, ya que sus pautas "integrales" no funcionarán en muchos sistemas, como lo descubrí por las malas varias veces.
Grawity
No hay problema, me encantaría pagar un -1 por una respuesta que no sea simplemente "integral", y ciertamente se ha ganado ese título.
Mechanical Fish
0

Dejé de tratar de resolver esto e hice un script ( ~/.shell-setup) que obtuve de todos los demás.

Este enfoque requiere ~/.shell-setuptener dos características:

  1. Solo se ejecuta una vez, incluso cuando se obtiene repetidamente (use Incluir guardias )
  2. No genere ninguna salida no deseada (detectar cuando la salida está bien)

El n. ° 1 es bastante estándar, aunque quizás no se usa mucho en los scripts de shell.

# 2 es más complicado. Esto es lo que uso en bash:

if [ "" == "$BASH_EXECUTION_STRING" -a "" == "$DESKTOP_SESSION" ]; then
    echo "Hello user!" # ... etc
fi

Desafortunadamente, no recuerdo cómo se me ocurrió eso, o por qué no fue suficiente detectar un shell interactivo .

ShadSterling
fuente
-2

Ponga todo .bashrcy luego fuente .bashrcde.profile

Desde la página de manual de bash (en OS X 10.9):

Cuando se inicia un shell interactivo que no es un shell de inicio de sesión, bash lee y ejecuta comandos desde ~ / .bashrc, si ese archivo existe. Esto puede inhibirse utilizando la opción --norc. La opción --rcfile file forzará a bash a leer y ejecutar comandos desde el archivo en lugar de ~ / .bashrc

El texto anterior es la razón por la cual todo se coloca .bashrc. Sin embargo, hay un comportamiento un poco diferente cuando se trata de un shell de inicio de sesión. Nuevamente, citando la página del manual:

Cuando se invoca bash como un shell de inicio de sesión interactivo o como un shell no interactivo con la opción --login, primero lee y ejecuta comandos del 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 del primero que existe y es legible. La opción --noprofile se puede usar cuando se inicia el shell para inhibir este comportamiento.

.profilese lee para shells de inicio de sesión, pero .bashrcno lo es. Duplicar todo ese material .bashrces malo ™, por lo que debemos buscarlo para que .profileel comportamiento permanezca constante.

Sin embargo, no desea obtener .bashrcde forma .profileincondicional. Consulte los comentarios y otras respuestas para obtener detalles adicionales.

mat-
fuente
44
-1, NO fuente .bashrcde .profile. Ver la respuesta de @ DanRabinowitz.
nyuszika7h
Al menos no incondicionalmente.
nyuszika7h
[ -n "$BASH" -a -f ~/.bashrc ] && . ~/.bashrcsería un dulce en línea para .profile.
John WH Smith
@ nyuszika7h, ¿por qué no? Todos parecen sugerir hacerlo.
Pacerier