En mi instalación de Arch, /etc/bash.bashrcy /etc/skel/.bashrccontiene estas líneas:
# If not running interactively, don't do anything
[[ $- != *i* ]] && return
En Debian, /etc/bash.bashrctiene:
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
Y /etc/skel/.bashrc:
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
Según man bash, sin embargo, los shells no interactivos ni siquiera leen estos archivos:
When bash is started non-interactively, to run a shell script, for
example, it looks for the variable BASH_ENV in the environment, expands
its value if it appears there, and uses the expanded value as the name
of a file to read and execute. Bash behaves as if the following com‐
mand were executed:
if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi
but the value of the PATH variable is not used to search for the file‐
name.
Si entiendo correctamente, los *.bashrcarchivos solo se leerán si BASH_ENVestá configurado para señalarlos. Esto es algo que no puede suceder por casualidad y solo ocurrirá si alguien ha establecido explícitamente la variable en consecuencia.
Eso parece romper la posibilidad de que las secuencias de comandos obtengan .bashrcautomáticamente a un usuario mediante la configuración BASH_ENV, algo que podría ser útil. Dado que bash nunca leerá estos archivos cuando se ejecute de forma no interactiva a menos que se le indique explícitamente que lo haga, ¿por qué los *bashrcarchivos predeterminados no lo permiten?

Respuestas:
Esta es una pregunta que iba a publicar aquí hace unas semanas. Al igual que terdon , entendí que a
.bashrcsolo se obtiene para shells interactivos de Bash, por lo que no debería ser necesario.bashrcverificar si se está ejecutando en un shell interactivo. Confusamente, todas las distribuciones que uso (Ubuntu, RHEL y Cygwin) tenían algún tipo de verificación (prueba$-o$PS1) para garantizar que el shell actual sea interactivo. No me gusta la programación de culto de carga, así que empecé a entender el propósito de este código en mi.bashrc.Bash tiene un estuche especial para proyectiles remotos
Después de investigar el problema, descubrí que los proyectiles remotos se tratan de manera diferente. Si bien los shells Bash no interactivos normalmente no ejecutan
~/.bashrccomandos al inicio, se hace un caso especial cuando el demonio de shell remoto invoca el shell :Ejemplo
Inserte lo siguiente al comienzo de un control remoto
.bashrc. (Si.bashrcproviene de.profileo.bash_profile, desactívelo temporalmente durante la prueba):Ejecute los siguientes comandos localmente:
iin$-indica que el shell no es interactivo .-en$0indica que la cáscara no es un shell de entrada .Las funciones de shell definidas en el control remoto
.bashrctambién se pueden ejecutar:Me di cuenta de que la
~/.bashrcestá solamente proceden cuando se especifica un comando como argumento parassh. Esto tiene sentido: cuandosshse usa para iniciar un shell de inicio de sesión normal.profileo cuando.bash_profilese ejecuta (y.bashrcsolo se obtiene si uno de estos archivos lo hace explícitamente).El principal beneficio que puedo ver al haber
.bashrcobtenido al ejecutar un comando remoto (no interactivo) es que se pueden ejecutar funciones de shell. Sin embargo, la mayoría de los comandos en un típico.bashrcsolo son relevantes en un shell interactivo, por ejemplo, los alias no se expanden a menos que el shell sea interactivo.Las transferencias de archivos remotas pueden fallar
Esto no suele ser un problema cuando
rshosshse utiliza para iniciar un intérprete interactivo de ingreso o cuando los proyectiles no interactivas se utilizan para ejecutar comandos. Sin embargo, puede ser un problema para programas comorcp,scpysftpque usan shells remotos para transferir datos.Resulta que el shell predeterminado del usuario remoto (como Bash) se inicia implícitamente cuando se usa el
scpcomando. No se menciona esto en la página de manual, solo una mención que sescputilizasshpara la transferencia de datos. Esto tiene la consecuencia de que si.bashrccontiene algún comando que imprima a la salida estándar, las transferencias de archivos fallarán , por ejemplo, scp falla sin error .Vea también este informe de error relacionado con Red Hat de hace 15 años, scp se rompe cuando hay un comando echo en / etc / bashrc (que finalmente se cerró como
WONTFIX).Por qué
scpysftpfallarSCP (Copia segura) y SFTP (Protocolo seguro de transferencia de archivos) tienen sus propios protocolos para que los extremos locales y remotos intercambien información sobre los archivos que se transfieren. Cualquier texto inesperado del extremo remoto se interpreta (erróneamente) como parte del protocolo y la transferencia falla. De acuerdo con un FAQ del Snail Book
Detalles del protocolo SCP
Para aquellos interesados en los detalles de cómo funciona SCP, encontré información interesante en Cómo funciona el protocolo SCP, que incluye detalles sobre cómo ejecutar scp con perfiles de shell habladores en el lado remoto. :
Conclusión / TLDR
La mayoría de las declaraciones en un típico
.bashrcsolo son útiles para un shell interactivo, no cuando se ejecutan comandos remotos conrshossh. En la mayoría de estas situaciones, no es deseable establecer variables de shell, alias y definir funciones, y la impresión de cualquier texto para estandarizar es activamente perjudicial si se transfieren archivos usando programas comoscposftp. Salir después de verificar que el shell actual no es interactivo es el comportamiento más seguro para.bashrc.fuente
La página de manual no menciona que
bashtambién hay fuentes.bashrcpara shells remotos no interactivos, como enhttp://git.savannah.gnu.org/cgit/bash.git/tree/shell.c#n1010
http://git.savannah.gnu.org/cgit/bash.git/tree/shell.c#n1050
fuente
.bash_profileexhibiría el mismo comportamiento.rsh(que nunca he usado) fuentes~/.bashrc? ¿Y eso, por extensión, las distribuciones de Linux lo bloquean porbashsi alguien intenta ejecutar un scriptrsh?ssh serverno debería tocar.bashrcya que de todos modos es un shell de inicio de sesión. No, a menos que su sistema sea uno de esos de donde provenga ~ / .bashrc`~/.profile. Yssh server commandni siquiera debería hacer eso. Ciertamente no en mi sistema.bashfuente, no a larshfuente. :) El comentario también se aplicassh, fue escrito hace mucho tiempo. Ver respuesta actualizada con más fuente.echoen la parte superior de/etc/bash.bashrcy~/.bashrc(antes de las pruebas de shell interactivas) y luego ssh en la máquina de destino conssh server hostnamey mientrashostnameestaba en ejecución, no vi ninguno de mis ecos. ¿Es que mishell_level(lo que sea que sea) no lo es<2?Por convención,
.bashrces el lugar donde el usuario almacena la configuración personalizada para el shell.Estas configuraciones personalizadas pueden ser variables de entorno, alias, avisos sofisticados. Con un shell no interactivo, esas cosas sin sentido no tienen sentido. Además, se puede llamar a un shell no interactivo en muchos contextos, no está seguro de que esas variables de entorno puedan conducir a un caso falso negativo o incluso a seguridad vulnerable.
Un ejemplo más cercano es un alias como:
Luego cuelga su shell no interactivo para siempre.
Por lo tanto, la verificación se realiza en la parte superior
.bashrcpara garantizar que no tengamos problemas.Debido a que el shell se puede llamar como un shell de inicio de sesión no interactivo , entonces el origen explícito de bloques
*bashrcno tiene sentido.Cuando la cáscara se llama como shell de entrada no interactivo , es fuente
/etc/profile, a continuación, la fuente de la primera que se encuentra en~/.bash_profile,~/.bash_loginy~/.profile:Nada impide que esos archivos se aprovisionen
.bashrc, por lo que hacer la comprobación interna.bashrces más seguro y simplifica las cosas.fuente
*bashrcarchivos en absoluto. Mi pregunta es por qué varios proveedores de Linux se toman la molestia de bloquear explícitamente que los shells no interactivos lean estos archivos si estos no son leídos por shells no interactivos de todos modos..bash_profile, que puede ser source.bashrc.$BASH_ENV. Ambos*profiley*bashrcson ignorados. O, al menos, eso es lo que dice la página del manual. Sin embargo, como Mikel ha mostrado, la página del manual podría estar mintiendo.bash -l -c :invocar un shell de inicio de sesión no interactivo?--login100 veces pero, aparentemente, nunca se había registrado. ¡Gracias!