Na minha instalação do Arch, /etc/bash.bashrc
e /etc/skel/.bashrc
contenha estas linhas:
# If not running interactively, don't do anything
[[ $- != *i* ]] && return
No Debian, /etc/bash.bashrc
tem:
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
E /etc/skel/.bashrc
:
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
De acordo com man bash
, no entanto, os shells não interativos nem lêem esses arquivos:
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.
Se bem entendi, os *.bashrc
arquivos serão lidos apenas se BASH_ENV
estiverem definidos para apontá-los. Isso é algo que não pode acontecer por acaso e só ocorrerá se alguém tiver definido explicitamente a variável de acordo.
Isso parece quebrar a possibilidade de os scripts originarem .bashrc
automaticamente o usuário, configurando BASH_ENV
algo que pode ser útil. Dado que o bash nunca lerá esses arquivos quando executado de maneira não interativa, a menos que seja explicitamente instruído a fazê-lo, por que os *bashrc
arquivos padrão não o permitem?
Respostas:
Esta é uma pergunta que eu ia postar aqui há algumas semanas. Como o terdon , entendi que o a
.bashrc
é fornecido apenas para shells Bash interativos, portanto não há necessidade de.bashrc
verificar se ele está sendo executado em um shell interativo. Confusamente, todas as distribuições que eu uso (Ubuntu, RHEL e Cygwin) tiveram algum tipo de verificação (teste$-
ou$PS1
) para garantir que o shell atual seja interativo. Eu não gosto de programação de cultos de carga, então comecei a entender o propósito deste código no meu.bashrc
.Bash tem um caso especial para reservatórios remotos
Depois de pesquisar o problema, descobri que os shells remotos são tratados de maneira diferente. Enquanto shells Bash não interativos normalmente não executam
~/.bashrc
comandos na inicialização, um caso especial é feito quando o shell é chamado pelo daemon de shell remoto :Exemplo
Insira o seguinte no início de um controle remoto
.bashrc
. (Se.bashrc
for originado por.profile
ou.bash_profile
, desative-o temporariamente durante o teste):Execute os seguintes comandos localmente:
i
in$-
indica que o shell não é interativo .-
em$0
indica que a casca não é um shell de login .As funções de shell definidas no controle remoto
.bashrc
também podem ser executadas:Percebi que o só
~/.bashrc
é originado quando um comando é especificado como argumento para . Isso faz sentido: quando é usado para iniciar um shell de logon regular ou é executado (e só é originado se explicitamente feito por um desses arquivos).ssh
ssh
.profile
.bash_profile
.bashrc
O principal benefício que posso ver de ter
.bashrc
originado ao executar um comando remoto (não interativo) é que as funções do shell podem ser executadas. No entanto, a maioria dos comandos de um típico.bashrc
é relevante apenas em um shell interativo, por exemplo, os aliases não são expandidos, a menos que o shell seja interativo.Transferências remotas de arquivos podem falhar
Isso geralmente não é um problema quando
rsh
oussh
é usado para iniciar um shell de logon interativo ou quando shells não interativos são usados para executar comandos. No entanto, pode ser um problema para programas comorcp
,scp
esftp
que usam shells remotos para transferir dados.Acontece que o shell padrão do usuário remoto (como o Bash) é implicitamente iniciado ao usar o
scp
comando. Não há menção a isso na página de manual - apenas uma mençãoscp
usadassh
para sua transferência de dados. Isso tem a conseqüência de que, se.bashrc
contiver algum comando impresso na saída padrão, a transferência de arquivos falhará , por exemplo, scp falhará sem erros .Veja também este relatório de bug relacionado ao Red Hat de 15 anos atrás, o scp quebra quando existe um comando echo no / etc / bashrc (que acabou sendo fechado como
WONTFIX
).Por que
scp
esftp
falharO SCP (cópia segura) e o SFTP (Protocolo seguro de transferência de arquivos) têm seus próprios protocolos para as extremidades local e remota para trocar informações sobre os arquivos que estão sendo transferidos. Qualquer texto inesperado da extremidade remota é (incorretamente) interpretado como parte do protocolo e a transferência falha. De acordo com uma FAQ do Snail Book
Detalhes do protocolo SCP
Para aqueles interessados nos detalhes de como o SCP funciona, encontrei informações interessantes em Como o protocolo SCP funciona, que inclui detalhes sobre Executando o scp com perfis de shell falante no lado remoto? :
Conclusão / TLDR
A maioria das instruções típicas
.bashrc
é útil apenas para um shell interativo - não ao executar comandos remotos comrsh
oussh
. Na maioria dessas situações, a definição de variáveis de shell, aliases e funções de definição não é desejada - e imprimir qualquer texto para padronizar é ativamente prejudicial ao transferir arquivos usando programas comoscp
ousftp
. Sair depois de verificar se o shell atual é não interativo é o comportamento mais seguro para.bashrc
.fonte
A página de manual esquece de mencionar que
bash
também fontes.bashrc
para shells remotos não interativos, como emhttp://git.savannah.gnu.org/cgit/bash.git/tree/shell.c#n1010
http://git.savannah.gnu.org/cgit/bash.git/tree/shell.c#n1050
fonte
.bash_profile
exibirá o mesmo comportamento.rsh
(que eu nunca usei) fontes~/.bashrc
? E que, por extensão, as distros do Linux o bloqueiambash
apenas no caso de alguém tentar executar um scriptrsh
?ssh server
não deve tocar,.bashrc
pois é um shell de login de qualquer maneira. A menos que o seu sistema seja um daqueles de onde provém ~ / .bashrc`~/.profile
. Essh server command
nem deveria fazer isso. Certamente não está no meu sistema.bash
fonte, não àrsh
fonte. :) O comentário também se aplicassh
, ele foi escrito há muito tempo. Veja a resposta atualizada com mais fonte.echo
na parte superior/etc/bash.bashrc
e~/.bashrc
(antes dos testes interativos do shell) e depois ssh na máquina de destino comssh server hostname
e enquantohostname
estava sendo executado, não vi nenhum dos meus ecos. Será que o meushell_level
(seja o que for) não é<2
?Por convenção,
.bashrc
é o local onde o usuário armazena a configuração de customização para o shell.Essas configurações personalizadas podem ser variáveis de ambiente, aliases, prompt sofisticado. Com um shell não interativo, essas coisas não têm sentido. Além disso, um shell não interativo pode ser chamado em muitos contextos, você não tem certeza de que essas variáveis de ambiente podem levar a casos negativos falsos ou mesmo vulneráveis à segurança.
Um exemplo mais próximo é um alias como:
Em seguida, pendure seu shell não interativo para sempre.
Portanto, a verificação é executada na parte superior
.bashrc
para garantir que não tenhamos problemas.Como o shell pode ser chamado de shell de logon não interativo , bloquear explicitamente a fonte
*bashrc
não faz sentido.Quando o shell foi chamado como shell de login não-interativo , é fonte
/etc/profile
e, em seguida fonte o primeiro encontrado em~/.bash_profile
,~/.bash_login
e~/.profile
:Nada impede que esses arquivos sejam adquiridos por
.bashrc
si, portanto, fazer a verificação interna.bashrc
é mais seguro e simplificar as coisas.fonte
*bashrc
arquivos. Minha pergunta é por que vários fornecedores de Linux se dão ao trabalho de impedir explicitamente que shells não interativos leiam esses arquivos se esses arquivos não são lidos por shells não interativos de qualquer maneira..bash_profile
, o que pode ser fonte.bashrc
.$BASH_ENV
. Ambos*profile
e*bashrc
são ignorados. Ou, pelo menos, é o que a página de manual diz. No entanto, como Mikel mostrou, a página de manual pode estar mentindo.bash -l -c :
invocar um shell de logon não interativo?--login
100 vezes, mas, aparentemente, nunca havia se registrado. Obrigado!