En mi instalación de Arch, /etc/bash.bashrc
y /etc/skel/.bashrc
contiene estas líneas:
# If not running interactively, don't do anything
[[ $- != *i* ]] && return
En Debian, /etc/bash.bashrc
tiene:
# 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 *.bashrc
archivos solo se leerán si BASH_ENV
está 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 .bashrc
automá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 *bashrc
archivos predeterminados no lo permiten?
Respuestas:
Esta es una pregunta que iba a publicar aquí hace unas semanas. Al igual que terdon , entendí que a
.bashrc
solo se obtiene para shells interactivos de Bash, por lo que no debería ser necesario.bashrc
verificar 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
~/.bashrc
comandos 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.bashrc
proviene de.profile
o.bash_profile
, desactívelo temporalmente durante la prueba):Ejecute los siguientes comandos localmente:
i
in$-
indica que el shell no es interactivo .-
en$0
indica que la cáscara no es un shell de entrada .Las funciones de shell definidas en el control remoto
.bashrc
también se pueden ejecutar:Me di cuenta de que la
~/.bashrc
está solamente proceden cuando se especifica un comando como argumento parassh
. Esto tiene sentido: cuandossh
se usa para iniciar un shell de inicio de sesión normal.profile
o cuando.bash_profile
se ejecuta (y.bashrc
solo se obtiene si uno de estos archivos lo hace explícitamente).El principal beneficio que puedo ver al haber
.bashrc
obtenido 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.bashrc
solo 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
rsh
ossh
se 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
,scp
ysftp
que usan shells remotos para transferir datos.Resulta que el shell predeterminado del usuario remoto (como Bash) se inicia implícitamente cuando se usa el
scp
comando. No se menciona esto en la página de manual, solo una mención que sescp
utilizassh
para la transferencia de datos. Esto tiene la consecuencia de que si.bashrc
contiene 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é
scp
ysftp
fallarSCP (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
.bashrc
solo son útiles para un shell interactivo, no cuando se ejecutan comandos remotos conrsh
ossh
. 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 comoscp
osftp
. 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
bash
también hay fuentes.bashrc
para 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_profile
exhibiría el mismo comportamiento.rsh
(que nunca he usado) fuentes~/.bashrc
? ¿Y eso, por extensión, las distribuciones de Linux lo bloquean porbash
si alguien intenta ejecutar un scriptrsh
?ssh server
no debería tocar.bashrc
ya 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 command
ni siquiera debería hacer eso. Ciertamente no en mi sistema.bash
fuente, no a larsh
fuente. :) El comentario también se aplicassh
, fue escrito hace mucho tiempo. Ver respuesta actualizada con más fuente.echo
en la parte superior de/etc/bash.bashrc
y~/.bashrc
(antes de las pruebas de shell interactivas) y luego ssh en la máquina de destino conssh server hostname
y mientrashostname
estaba 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,
.bashrc
es 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
.bashrc
para 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
*bashrc
no 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_login
y~/.profile
:Nada impide que esos archivos se aprovisionen
.bashrc
, por lo que hacer la comprobación interna.bashrc
es más seguro y simplifica las cosas.fuente
*bashrc
archivos 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*profile
y*bashrc
son 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?--login
100 veces pero, aparentemente, nunca se había registrado. ¡Gracias!