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

56

De vez em quando eu farei algo como

ssh user@host sudo thing

e eu sou lembrado que o ssh não aloca uma pseudo-tty por padrão. Por que isso não acontece? Quais benefícios eu estaria perdendo se eu aliasse ssh a ssh -t ?

    
por Chas. Owens 06.05.2014 / 16:06

5 respostas

62

A principal diferença é o conceito de interatividade . É semelhante a executar comandos localmente dentro de um script, em vez de digitá-los por conta própria. É diferente em que 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 uma entrada adicional sem quebrar as coisas. Existem muitos programas que ignoram a etapa de solicitar a entrada do usuário, se não houver um terminal presente, e isso é bom. Isso faria com que os scripts fossem interrompidos desnecessariamente.
  • Sua entrada será enviada ao servidor remoto pela duração do comando. Isso inclui seqüências de controle. Embora uma quebra de Ctrl-c normalmente faça com que um loop no comando ssh seja interrompido imediatamente, suas seqüências de controle serão enviadas ao servidor remoto. Isso resulta na necessidade de "martelar" o pressionamento de tecla para garantir que ele chegue quando o controle deixar o comando ssh, mas antes que o próximo comando ssh seja iniciado.

Gostaria de evitar o uso de ssh -t em scripts não assistidos, como crons. Um shell não interativo solicitando que um comando remoto se comporte interativamente para a entrada está pedindo por 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 aliasing ssh to ssh -t , você pode esperar obter um retorno de carro extra nas extremidades de sua linha. Pode não ser visível para você, mas está lá; Ele aparecerá como ^M quando canalizado para cat -e . Você deve então despender o esforço adicional de garantir que esse código de controle não seja atribuído às suas variáveis, especialmente se você for inserir essa saída em um banco de dados.
  • Existe também o risco de os programas assumirem que podem renderizar uma saída que não seja amigável para o redirecionamento de arquivos. Normalmente, se você redirecionar o STDOUT para um arquivo, o programa reconhecerá que o seu STDOUT não é um terminal e omite 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 tal distinção e você acabará com o lixo do terminal. no seu arquivo de saída. Redirecionar a saída para um arquivo na extremidade remota da conexão ainda deve funcionar como esperado.

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

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

Embora seja possível contornar esses problemas, você inevitavelmente se esquecerá de criar scripts em torno deles. Todos nós fazemos em algum momento. Os membros da sua equipe também podem não perceber / lembrar que esse alias está em vigor, o que, por sua vez, criará problemas para você quando eles escrevem scripts que usam seu alias.

Aliasing ssh to ssh -t é um caso em que você estará violando o princípio de design de menos surpresa ; as pessoas encontrarão problemas que não esperam e podem não entender o que as está causando.

    
por 06.05.2014 / 17:02
24

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 do SSH como ~C são < strong> não suportado ; isso torna seguro para 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 scp ou rsync que usam SSH para transferência de dados. Esta descrição detalhada de como funciona o protocolo SCP explica como o protocolo SCP consiste em uma mistura de mensagens de protocolo textuais e dados de arquivos binários.

O OpenSSH ajuda a protegê-lo de si mesmo

Vale a pena notar que, mesmo se o sinalizador -t for usado, o cliente OpenSSH ssh se recusará a alocar um pseudo-terminal se detectar que o fluxo stdin 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, (sensivelmente) não importa se stdout ou stderr são redirecionados:

$ ssh -t anthony@remote_host 'echo $TERM' >| ssh_output
Connection to remote_host closed.
    
por 04.01.2016 / 17:10
3

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

/etc/sudoers
...
Defaults requiretty

Sem sudo

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

E com o 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 é desabilitar a translate newline para a linha de retorno de carro com stty -onlcr

$ ssh -t user@host stty -onlcr\; sudo echo -e 'foo\nbar' | cat -e
foo$
    bar$
        Connection to localhost closed.
    
por 01.08.2016 / 14:51
1

Pense em compatibilidade com versões anteriores.

Os dois modos principais de ssh são o login interativo com um comando tty e especificado sem tty, porque esses eram os recursos exatos de rlogin e rsh , respectivamente. O ssh precisava fornecer um superconjunto de recursos rlogin / rsh para ter sucesso como um substituto.

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

    
por 06.05.2014 / 19:24
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 um tipo de "shell" para o servidor remoto. Para servidores que não não concedem acesso ao shell, mas permitem SSH (ou seja, o Github é um exemplo conhecido para acesso SFTP), o uso desse sinalizador fará com que o servidor rejeite sua conexão.

O shell também tem todas as suas variáveis ambientais (como $PATH ), portanto, executar scripts geralmente precisa de um tty para funcionar.

    
por 06.05.2014 / 16:45