`ssh <host>` é um shell de login, mas `ssh <host> <comando>` não é?

12

Percebi que quando executo um comando diretamente em um host SSH usando a ssh <host> <command>sintaxe, vejo a saída de, .bashrcmas 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 .bashrcpor 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_profiletemporariamente 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_profilee .bashrcé que o primeiro é para shells de login, enquanto o último é para shells interativos e sem login .

Concluí o seguinte:

  1. ssh <host>apenas fontes .bash_profile, enquanto
  2. ssh <host> <command>apenas fontes .bashrc, o que significa
  3. 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?

Ryan Lue
fonte
saída de .bashrc? Esse arquivo não deve produzir nenhuma saída. Qualquer saída de .bashrcpode quebrar todas as ferramentas usando ssh como transporte.
kasperd
Justo. Nesse caso, algumas linhas .bashrcestavam lançando um erro, enquanto linhas semelhantes .bash_profilenão estavam. Aproveitei a oportunidade para investigar a discrepância antes de consertar as linhas ofensivas.
Ryan Lue

Respostas:

12

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:

 If command is specified, it is executed on the remote host instead of a
 login shell.

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 sshfaç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 ~/.bashrcque está acontecendo claramente aqui. bashestá realmente tentando nos ajudar aqui. Dos documentos

Chamado pelo daemon de shell remoto

O Bash tenta determinar quando está sendo executado com sua entrada padrão conectada a uma conexão de rede, como quando executada pelo daemon de shell remoto, geralmente rshd, ou pelo daemon de shell seguro sshd. Se o Bash determinar que está sendo executado dessa maneira, ele lê e executa comandos de ~ / .bashrc, se esse arquivo existe e é legível. Isso não será feito se invocado como sh. A opção --norc pode ser usada para inibir esse comportamento, e a opção --rcfile pode ser usada para forçar a leitura de outro arquivo, mas nem o rshd nem o sshd geralmente invocam o shell com essas opções ou permitem que sejam especificados.

Eric Renouf
fonte
"... é executado no host remoto em vez de um shell de login." Eu não entendo essa dicotomia. O comando é executado no host remoto em vez de em um shell de logon ou o comando é executado no host remoto, em vez de um shell de logon sendo executado lá? Se o primeiro, como é / ou? (normalmente não são os dois? ) Se o último, ainda é executado no contexto de algum shell, não é? (uma interativa e sem login?) Então, minha pergunta também é sobre semântica - o que significa "shell de login" e por que o OpenSSH foi projetado para não criar um para comandos únicos?
quer
@RyanLue Os diferentes "sabores" de shells tornam cada tarefa mais fácil / mais segura / otimizada etc. Enquanto fazem um sshrequer 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. comando
Eric Renouf
"Então, de fato, existe um shell que é executado, presumo principalmente configurar o ambiente ..." <, mas apenas experimentei isso e parece que ssh <host> <command>não herda o ambiente de nenhum shell de login existente. Por exemplo, $ ssh <host> \$PATHretorna 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?
precisa
"... os implementadores aparentemente decidiram que, em algumas circunstâncias, por exemplo, solicitando que ele execute um comando e retorne, não precisa / se beneficia das etapas extras que um shell de logon executa, e então pula isso." <também, procurando especificamente esclarecimentos / informações sobre essa opção de design. Eu defino o meu PATHem .profile- não é que exatamente o tipo de coisa que você quer carregar antes de executar um comando arbitrário em um host remoto?
precisa
1
@RyanLue, o servidor Boks ssh distingue usos distintos do ssh e pode conceder permissões para cada um. Login remoto, execução remota, cópia remota. Talvez isso ajude a entender por que você teria o comportamento que descreve. O login remoto (uso interativo) pode ser pedir demais em um ambiente de alta segurança. O Openssh pode ser restringido pelo uso de rbash / rksh e 'logout' em .bash_profile ou chroot.
bbaassssiiee
4

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 o sshdprocesso do servidor e o shell; ssh host commandusa tubos entre sshde command, 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 -te -T. Por exemplo, para fazer login em uma máquina remota e reconectar imediatamente uma screensessão suspensa , é necessário fazer ssh -t host screen -R; ssh host screen -Rfará com screenque 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.

zwol
fonte
1

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:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

Isso significa que, dependendo de como você está acessando o sistema, esse arquivo carrega o código dentro ou não.

Genaro Morales
fonte
Ok, mas isso levanta uma questão interessante: .bashrcpode 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" / $PS1variável). Mas ssh <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?
precisa