Percebi que quando executo um comando diretamente em um host SSH usando a ssh <host> <command>
sintaxe, vejo a saída de, .bashrc
mas não a saída de .bash_profile
(ou .profile
).
Por exemplo, se eu colocar o seguinte comando na parte superior dos dois arquivos,
echo ${BASH_SOURCE[0]}
e manualmente fonte .bash_profile
(que fontes .bashrc
por sua vez), vou ver
$ . .bash_profile
.bash_profile
.bashrc
Essa é a mesma saída que eu vejo se fizer login neste computador remotamente via SSH, usando o ssh <host>
formulário do comando. (E se eu guardar .bash_profile
temporariamente em outro lugar temporariamente, nenhuma dessas linhas será reproduzida.)
No entanto, se eu executar um comando diretamente na máquina remota com o ssh <host> <command>
formato de ssh
, a saída será assim:
$ ssh <host> echo foo
/home/rlue/.bashrc
foo
Meu entendimento é que a diferença entre .bash_profile
e .bashrc
é que o primeiro é para shells de login, enquanto o último é para shells interativos e sem login .
Concluí o seguinte:
ssh <host>
apenas fontes.bash_profile
, enquantossh <host> <command>
apenas fontes.bashrc
, o que significa- o primeiro é um shell de login e o segundo não.
Essas conclusões estão corretas? Por que é ssh <host> <command>
tratado como um shell interativo e sem login? O SSH ainda não está efetuando login na máquina remota para executar o comando?
.bashrc
? Esse arquivo não deve produzir nenhuma saída. Qualquer saída de.bashrc
pode quebrar todas as ferramentas usando ssh como transporte..bashrc
estavam lançando um erro, enquanto linhas semelhantes.bash_profile
não estavam. Aproveitei a oportunidade para investigar a discrepância antes de consertar as linhas ofensivas.Respostas:
O OpenSSH (provavelmente o que você está executando) decide se deve ou não criar um shell de login, e só o faz se você não estiver executando um comando específico. De
man ssh
:Portanto, é uma opção de implementação para o servidor ssh, se ele deseja criar um shell de login ou não, e se você der um comando para executar, isso não acontece.
Embora
ssh
faça um login, se você estiver executando um comando e sair, é muito mais parecido com a criação de um shell apenas para executar esse comando do que com um ambiente de login. Parece, dado que, as pessoas que escreviam o OpenSSH decidiram tratá-lo como esse tipo de tarefa.Eles criam um shell não interativo e sem login para executar o comando, porque esse é o espírito de executar um comando em outro contexto / shell. Normalmente, porém, shells não interativos não seriam automaticamente fonte do
~/.bashrc
que está acontecendo claramente aqui.bash
está realmente tentando nos ajudar aqui. Dos documentosfonte
ssh
requer um login, os implementadores aparentemente decidiram que, em algumas circunstâncias, por exemplo, pedindo para executar um comando e retornar, faça não precisam / se beneficiam das etapas extras que um shell de logon executa e, portanto, pulam isso. Portanto, de fato, existe um shell que é executado, presumo principalmente configurar o ambiente e, como o shell não será fornecido ao usuário que efetuou login, eles o tratam como se o usuário tivesse iniciado um novo shell para executar esse ambiente. comandossh <host> <command>
não herda o ambiente de nenhum shell de login existente. Por exemplo,$ ssh <host> \$PATH
retorna o caminho como seria sem procurar.bash_profile
(ou.profile
, por assim dizer) ... Em um sentido prático, por que você deseja contornar esse passo?PATH
em.profile
- não é que exatamente o tipo de coisa que você quer carregar antes de executar um comando arbitrário em um host remoto?O porquê desse comportamento está em um nível mais baixo do que os shells:
ssh host
(o caso "shell de login") usa um pseudoterminal no host remoto para se comunicar entre osshd
processo do servidor e o shell;ssh host command
usa tubos entresshd
ecommand
, em vez disso. Os pseudo-terminais são necessários para fazer uso interativo de um interpretador de comandos, como um shell, ou o modo " leitura-avaliação-impressão " de uma linguagem de script; eles implementam vários recursos amigáveis ao ser humano, como poder retroceder com erros de digitação. Mas eles têm mais sobrecarga e (dependendo da configuração) não permitem que dados arbitrários passem sem modificação, portanto o SSH evita usá-los quando a interação não está acontecendo.Às vezes, a heurística de comando / sem comando do SSH erra; ele pode ser substituído pelos botões
-t
e-T
. Por exemplo, para fazer login em uma máquina remota e reconectar imediatamente umascreen
sessão suspensa , é necessário fazerssh -t host screen -R
;ssh host screen -R
fará comscreen
que reclamar por não estar conectado a um terminal. Não consigo pensar em uma situação em que você realmente queira usar-T
, mas está lá se você encontrar uma.fonte
Primeiro você precisa ver os diferentes tipos, você pode ler isto:
/unix/170493/login-non-login-and-interactive-non-interactive-shells
Agora, se você abrir o bashrc, verá no início isso:
Isso significa que, dependendo de como você está acessando o sistema, esse arquivo carrega o código dentro ou não.
fonte
.bashrc
pode ser escrito para não ser originado se for chamado em um contexto não interativo ( ou seja, se não houver uma "declaração rápida" /$PS1
variável). Masssh <host> <command>
é decididamente não interativo ; isto é, não gera um prompt de comando. Então, por que o OpenSSH foi projetado para criar um prompt interativo sem login (que tenta se originar.bashrc
) para este caso de uso aparentemente interativo e não interativo?