Qual é o benefício de não alocar um terminal no ssh?

66

De vez em quando eu vou fazer algo como

ssh user@host sudo thing

e lembro que o ssh não aloca um pseudo-tty por padrão. Por que não? Quais os benefícios que eu estaria perdendo se eu alias sshpara ssh -t?

Chas. Owens
fonte
11
> Lembro que o ssh não aloca um psuedo-tty O que acontece? Enriqueceria a questão de entender qual é o problema.
Air
5
@ Air Não há um problema que eu estava tentando corrigir. Havia uma escolha de como o ssh é implementado que eu estava tentando entender. A pergunta é muito clara e a resposta de Andrew B trata bem da questão. A resposta pode ser resumida assim: correr ssh -tsempre é ruim porque pode fazer com que alguns comandos sejam quebrados de maneiras estranhas. Visto que a execução de um comando que precisa de um PTY sem um resulta em uma mensagem de erro clara de que você precisa de um terminal.
Chas. Owens

Respostas:

73

A principal diferença é o conceito de interatividade . É semelhante a executar comandos localmente dentro de um script, em vez de digitá-los você mesmo. É diferente, pois um comando remoto deve escolher um padrão e não interativo é mais seguro. (e geralmente mais honesto)

STDIN

  • Se um PTY for alocado, os aplicativos poderão detectar isso e saber que é seguro solicitar ao usuário informações adicionais sem interromper as coisas. Existem muitos programas que ignoram a etapa de solicitar entrada do usuário se não houver terminal presente, e isso é uma coisa boa. Isso faria com que os scripts travassem desnecessariamente caso contrário.
  • Sua entrada será enviada para o servidor remoto pela duração do comando. Isso inclui seqüências de controle. Enquanto uma Ctrl-cquebra normalmente faria com que um loop no comando ssh fosse interrompido imediatamente, suas seqüências de controle serão enviadas para o servidor remoto. Isso resulta em uma necessidade de "martelar" o pressionamento de tecla para garantir que ele chegue quando o controle sair do comando ssh, mas antes que o próximo comando ssh comece.

Eu recomendaria não usar ssh -tscripts autônomos, como crons. Um shell não interativo que solicita a um comando remoto que se comporte de maneira interativa está solicitando todos os tipos de problemas.

Você também pode testar a presença de um terminal em seus próprios scripts de shell. Para testar o STDIN com versões mais recentes do bash:

# fd 0 is STDIN
[ -t 0 ]; echo $?

STDOUT

  • Ao sshcriar um alias para ssh -t, você pode esperar um retorno de carro extra nas extremidades da sua linha. Pode não ser visível para você, mas está lá; aparecerá como ^Mquando canalizado cat -e. Em seguida, você deve fazer um esforço adicional para garantir que esse código de controle não seja atribuído às suas variáveis, principalmente se você deseja inserir essa saída em um banco de dados.
  • Também existe o risco de os programas assumirem que podem renderizar uma saída que não é amigável para o redirecionamento de arquivos. Normalmente, se você redirecionasse o STDOUT para um arquivo, o programa reconheceria que o seu STDOUT não é um terminal e omitiria qualquer código de cores. Se o redirecionamento STDOUT for da saída do cliente ssh e houver um PTY associado à extremidade remota do cliente, os programas remotos não poderão fazer essa distinção e você terminará com lixo de terminal no arquivo de saída. Redirecionar a saída para um arquivo na extremidade remota da conexão ainda deve funcionar conforme o esperado.

Aqui está o mesmo teste do bash do que antes, mas para STDOUT:

# fd 1 is STDOUT
[ -t 1 ]; echo $?

Embora seja possível contornar esses problemas, você inevitavelmente esquecerá o design de scripts. Todos nós fazemos em algum momento. Os membros da equipe também pode não perceber / lembre-se que este alias está no lugar, que por sua vez criar problemas para você quando eles escrever scripts que usam seus alias.

Aliasing sshpara ssh -té muito mais um caso onde você estará violando o princípio de projeto de menor surpresa ; as pessoas encontrarão problemas que não esperam e podem não entender o que está causando isso.

Andrew B
fonte
9
Um quase-se a impressão que eu tenho trabalhado em uma equipe que fez isso ...
Andrew B
No escopo coberto por esta resposta, é ótimo. Mas a questão tinha um escopo mais amplo, essencialmente querendo conhecer TODAS as diferenças (o que esperar). Informações adicionais: No nível do processo, -t PRIMEIRO alocará um tty e, em seguida, executará um shell (ao longo do caminho, fornecendo / etc / profile e ~ / .bash_profile) e, em seguida, executará o comando. Sem -t, o ssh INSTEAD fonte diferentes arquivos env (/etc/bash.bashrc, depois ~ / .bashrc) e então executa seu comando. Isto significa que você pode ver um comportamento muito diferente em cada um: mais curto $ PATH, talvez uma festa de erro 'unário' porque o var ENV você assumiu não está lá ...
Scott Prive
@Crossfit Abordamos o tópico de shells de login versus non nos comentários de outra resposta, mas não entramos em um colapso exaustivo das diferenças ambientais, porque o OP já havia considerado a pergunta respondida para suas necessidades particulares. Por favor, sinta-se à vontade para adicionar detalhes onde você vê espaço para fazê-lo, pois isso pode ajudar outras pessoas que se deparam com essas perguntas e respostas.
Andrew B
33

Caracteres de escape SSH e transferência de arquivos binários

Uma vantagem que não foi mencionada nas outras respostas é que, ao operar sem um pseudo-terminal , os caracteres de escape SSH , como não~C são suportados ; isso torna seguro para os programas transferir arquivos binários que podem conter essas seqüências.

Prova de conceito

Copie um arquivo binário usando um pseudo-terminal:

$ ssh -t anthony@remote_host 'cat /usr/bin/free' > ~/free
Connection to remote_host closed.

Copie um arquivo binário sem usar um pseudo-terminal:

$ ssh anthony@remote_host 'cat /usr/bin/free' > ~/free2

Os dois arquivos não são os mesmos:

$ diff ~/free*
Binary files /home/anthony/free and /home/anthony/free2 differ

O que foi copiado com um pseudo-terminal está corrompido:

$ chmod +x ~/free*
$ ./free
Segmentation fault

enquanto o outro não é:

$ ./free2
             total       used       free     shared    buffers     cached
Mem:       2065496    1980876      84620          0      48264    1502444
-/+ buffers/cache:     430168    1635328
Swap:      4128760        112    4128648

Transferindo arquivos pelo SSH

Isso é particularmente importante para programas como scpou rsyncque usam SSH para transferência de dados. Esta descrição detalhada de como o protocolo SCP funciona explica como o protocolo SCP consiste em uma mistura de mensagens de protocolo textuais e dados de arquivos binários.


O OpenSSH ajuda a proteger você de si mesmo

Vale ressaltar que, mesmo que o -tsinalizador seja usado, o sshcliente OpenSSH se recusará a alocar um pseudo-terminal se detectar que seu stdinfluxo não é um terminal:

$ echo testing | ssh -t anthony@remote_host 'echo $TERM'
Pseudo-terminal will not be allocated because stdin is not a terminal.
dumb

Você ainda pode forçar o cliente OpenSSH a alocar um pseudo-terminal com -tt:

$ echo testing | ssh -tt anthony@remote_host 'echo $TERM'
xterm

Em ambos os casos, (sensatamente) não se importa se é stdoutou stderré redirecionado:

$ ssh -t anthony@remote_host 'echo $TERM' >| ssh_output
Connection to remote_host closed.
Anthony G - justiça para Monica
fonte
2
Esse foi um ponto muito interessante que eu não havia considerado, obrigado por adicionar esta resposta!
Jenny D diz Restabelecer Monica
4

No host remoto, temos a ver com esta configuração:

/etc/sudoers
...
Defaults requiretty

Sem sudo

$ ssh -T user@host echo -e 'foo\\nbar' | cat -e
foo$
bar$

E com sudo

$ ssh -T user@host sudo echo -e 'foo\\nbar' | cat -e
sudo: sorry, you must have a tty to run sudo

Com o sudo, obtemos o retorno de carro extra

$ ssh -t user@host sudo echo -e 'foo\\nbar' | cat -e
foo^M$
      bar^M$
            Connection to localhost closed.

A solução é desativar a linha nova de conversão em linha de retorno de carro comstty -onlcr

$ ssh -t user@host stty -onlcr\; sudo echo -e 'foo\\nbar' | cat -e
foo$
    bar$
        Connection to localhost closed.
Christophe Morio
fonte
11
Bom, mas a saída é recuada /: Você sabe se pode devolver automaticamente o carro (como um unix)?
Boop
1

Pense em compatibilidade com versões anteriores.

Os dois modos principais do ssh são o logon interativo com um tty e o comando especificado sem um tty, porque esses eram os recursos exatos de rlogine rshrespectivamente. O ssh precisava fornecer um superconjunto de rlogin/ rshfeatures para ter sucesso como substituição.

Portanto, os padrões foram decididos antes do nascimento do ssh. Combinações como "Quero especificar um comando e obter um tty" precisavam ser acessadas com novas opções. Seja feliz que pelo menos nós tem essa opção agora, ao contrário de quando estávamos usando rsh. Não trocamos nenhum recurso útil para obter conexões criptografadas. Temos recursos de bônus!


fonte
0

De man ssh:

 -t      Force pseudo-tty allocation.  This can be used to execute arbi-
         trary screen-based programs on a remote machine, which can be
         very useful, e.g. when implementing menu services.  Multiple -t
         options force tty allocation, even if ssh has no local tty.

Isso permite que você obtenha uma espécie de "shell" para o servidor remoto. Para servidores que não concedem acesso ao shell, mas permitem SSH (ou seja, o Github é um exemplo conhecido para acesso ao SFTP), o uso desse sinalizador fará com que o servidor rejeite sua conexão.

O shell também possui todas as suas variáveis ​​ambientais (como $PATH), portanto, a execução de scripts geralmente precisa de um tty para funcionar.

Nathan C
fonte
11
Isso não responde à pergunta. Eu já sei como alocar um pseudo-tty. Quero saber por que nem sempre devo alocar um.
Chas. Owens
11
@ Chas.Owens Porque, como indiquei na resposta, alguns servidores SSH não permitem acesso tty e a conexão será interrompida se você solicitar um do servidor.
C # de Nathan C
5
Acho que você pode estar confundindo parte da sua terminologia. Não é um shell simplesmente porque um PTY está associado a ele. Há geralmente três tipos de shell: non-interactive, interactive, e login. loginé uma característica adicional dos outros dois tipos de shell. As permutações desses três determinam quais arquivos são originados no logon, o que, por sua vez, influencia como o ambiente será inicializado. (variáveis, como você estava mencionando)
Andrew B
3
@AndrewB Você está certo ... Eu aprendi algo com essa pergunta também. :)
Nathan C