¿Cuál es el beneficio de no asignar un terminal en ssh?

66

De vez en cuando haré algo como

ssh user@host sudo thing

y recuerdo que ssh no asigna un pseudo-tty por defecto. ¿Por qué no lo hace? ¿Qué beneficios tendría que estar perdiendo si un alias ssha ssh -t?

Chas Owens
fuente
1
> Me recuerda que ssh no asigna una psuedo-tty ¿Qué sucede? Enriquecería la pregunta para entender cuál es el problema.
Aire
55
@Air No hay un problema que intentara solucionar. Había una opción sobre cómo se implementaba ssh que estaba tratando de entender. La pregunta es muy clara y la respuesta de Andrew B aborda la pregunta muy bien. La respuesta se puede resumir así: correr ssh -tsiempre es malo porque puede hacer que algunos comandos se rompan de manera extraña. Mientras que ejecutar un comando que necesita un PTY sin uno da como resultado un mensaje de error claro de que necesita un terminal.
Chas. Owens

Respuestas:

73

La diferencia principal es el concepto de interactividad . Es similar a ejecutar comandos localmente dentro de un script, en lugar de escribirlos usted mismo. Es diferente en que un comando remoto debe elegir un valor predeterminado, y no interactivo es más seguro. (y generalmente lo más honesto)

STDIN

  • Si se asigna un PTY, las aplicaciones pueden detectar esto y saber que es seguro solicitar al usuario una entrada adicional sin interrumpir las cosas. Hay muchos programas que omitirán el paso de solicitar al usuario una entrada si no hay un terminal presente, y eso es algo bueno. De lo contrario, los scripts se colgarían innecesariamente.
  • Su entrada se enviará al servidor remoto mientras dure el comando. Esto incluye secuencias de control. Si bien una Ctrl-cinterrupción normalmente provocaría que un bucle en el comando ssh se interrumpa inmediatamente, sus secuencias de control se enviarán al servidor remoto. Esto da como resultado la necesidad de "martillar" la pulsación de tecla para garantizar que llegue cuando el control abandone el comando ssh, pero antes de que comience el siguiente comando ssh.

Advierto sobre el uso ssh -tde scripts desatendidos, como crons. Un shell no interactivo que le pide a un comando remoto que se comporte interactivamente para la entrada está pidiendo todo tipo de problemas.

También puede probar la presencia de un terminal en sus propios scripts de shell. Para probar STDIN con versiones más nuevas de bash:

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

STDOUT

  • Cuando aliasing ssha ssh -t, se puede esperar para obtener un retorno de carro adicional en los extremos de su línea. Puede que no sea visible para ti, pero está ahí; se mostrará como ^Mcuando se canaliza a cat -e. Luego debe realizar un esfuerzo adicional para asegurarse de que este código de control no se asigne a sus variables, especialmente si va a insertar esa salida en una base de datos.
  • También existe el riesgo de que los programas asuman que pueden generar resultados que no son amigables para la redirección de archivos. Normalmente, si fuera a redirigir STDOUT a un archivo, el programa reconocería que su STDOUT no es un terminal y omitiría cualquier código de color. Si la redirección STDOUT proviene de la salida del cliente ssh y hay un PTY asociado con el extremo remoto del cliente, los programas remotos no pueden hacer esa distinción y terminará con basura terminal en su archivo de salida. La redirección de salida a un archivo en el extremo remoto de la conexión debería funcionar como se esperaba.

Aquí está la misma prueba de bash que antes, pero para STDOUT:

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

Si bien es posible solucionar estos problemas, inevitablemente olvidará diseñar scripts a su alrededor. Todos lo hacemos en algún momento. Los miembros del equipo también no se dan cuenta / recordar que este alias está en su lugar, que a su vez crear problemas para usted cuando se escriben los scripts que utilizan sus alias.

Aliasing ssha ssh -testá en gran medida un caso en el que se le violando el principio de diseño de la menor sorpresa ; las personas se encontrarán con problemas que no esperan y pueden no entender lo que los está causando.

Andrew B
fuente
9
Uno casi tiene la impresión de que he trabajado en un equipo que ha hecho esto ...
Andrew B
En el ámbito cubierto por esta respuesta, es genial. Pero la pregunta tenía un alcance más amplio, esencialmente queriendo saber TODAS las diferencias (qué esperar). Información adicional: a nivel de proceso, -t PRIMERO asignará un tty y ENTONCES ejecutará un shell (en el camino, abastecimiento / etc / profile y ~ / .bash_profile) y ENTONCES ejecutará el comando. Sin -t, ssh INSTEAD buscará diferentes archivos env (/etc/bash.bashrc, luego ~ / .bashrc) y luego ejecutará su comando. Esto significa que puede ver un comportamiento muy diferente en cada uno: $ PATH más corto, tal vez un error bash 'unario' porque la variable ENV que asumió no está allí ...
Scott Prive
@Crossfit Cubrimos el tema de los shells de inicio de sesión versus no en los comentarios de otra respuesta, pero no entramos en un desglose exhaustivo de las diferencias ambientales porque el OP ya había considerado la pregunta respondida para sus necesidades particulares. Por favor, siéntase libre de agregar detalles donde vea espacio para hacerlo, ya que puede ayudar a otros que vienen a este Q&A.
Andrew B
33

Caracteres de escape SSH y transferencia de archivos binarios

Una ventaja que no se ha mencionado en las otras respuestas es que cuando se opera sin un pseudo-terminal , los caracteres de escape SSH como no~C son compatibles ; Esto hace que sea seguro para los programas transferir archivos binarios que pueden contener estas secuencias.

Prueba de concepto

Copie un archivo binario usando un pseudo-terminal:

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

Copie un archivo binario sin usar un pseudo-terminal:

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

Los dos archivos no son lo mismo:

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

El que se copió con un pseudo-terminal está dañado:

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

mientras que el otro no es:

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

Transferencia de archivos a través de SSH

Esto es particularmente importante para programas como scpo rsyncque usan SSH para la transferencia de datos. Esta descripción detallada de cómo funciona el protocolo SCP explica cómo el protocolo SCP consiste en una mezcla de mensajes de protocolo de texto y datos de archivos binarios.


OpenSSH ayuda a protegerte de ti mismo

Vale la pena señalar que incluso si -tse usa el indicador, el sshcliente OpenSSH se negará a asignar un pseudo-terminal si detecta que su stdinflujo no es un terminal:

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

Todavía puede forzar al cliente OpenSSH a asignar un pseudo-terminal con -tt:

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

En cualquier caso, (sensiblemente) no le importa si stdouto stderrse redirige:

$ ssh -t anthony@remote_host 'echo $TERM' >| ssh_output
Connection to remote_host closed.
Anthony G - justicia para Monica
fuente
2
Ese fue un punto muy interesante que no había considerado, ¡gracias por agregar esta respuesta!
Jenny D dice Restablecer a Mónica el
4

En el host remoto tenemos que ver con esta configuración:

/etc/sudoers
...
Defaults requiretty

Sin sudo

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

Y con sudo

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

Con sudo obtenemos el retorno de carro extra

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

La solución es deshabilitar la traducción nueva línea a carro retorno-nueva línea constty -onlcr

$ ssh -t user@host stty -onlcr\; sudo echo -e 'foo\\nbar' | cat -e
foo$
    bar$
        Connection to localhost closed.
Christophe Morio
fuente
1
Agradable, pero la salida está sangrada /: ¿Sabes si puedes devolverlo automáticamente (como unix)?
Boop
1

Piensa en la compatibilidad con versiones anteriores.

Los 2 modos principales de ssh son el inicio de sesión interactivo con tty y el comando especificado sin tty, porque esas eran las capacidades exactas de rloginy rshrespectivamente. ssh necesitaba proporcionar un superconjunto de rlogin/ rshcaracterísticas para tener éxito como reemplazo.

Entonces, los valores predeterminados se decidieron antes de que naciera ssh. Se debía acceder a combinaciones como "Quiero especificar un comando y obtener un tty" con nuevas opciones. Alégrate de que por lo menos tenemos esa opción ahora, a diferencia de cuando estábamos usando rsh. No intercambiamos ninguna característica útil para obtener conexiones cifradas. ¡Tenemos características adicionales!


fuente
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.

Esto le permite obtener una especie de "shell" para el servidor remoto. Para los servidores que no otorgan acceso de shell pero permiten SSH (es decir, Github es un ejemplo conocido de acceso SFTP), el uso de este indicador hará que el servidor rechace su conexión.

El shell también tiene todas sus variables de entorno (como $PATH), por lo que ejecutar scripts generalmente necesita un tty para funcionar.

Nathan C
fuente
1
Esto no responde la pregunta. Ya sé cómo asignar un pseudo-tty. Quiero saber por qué no siempre debería asignar uno.
Chas. Owens
1
@ Chas.Owens Porque, como señalé en la respuesta, algunos servidores SSH no permiten el acceso tty y se cortará la conexión si solicita uno del servidor.
Nathan C
55
Creo que puede estar confundiendo parte de su terminología. No es un shell simplemente porque un PTY está asociado con él. En general, existen tres tipos de shell: non-interactive, interactive, y login. logines una característica adicional de los otros dos tipos de shell. Las permutaciones de estos tres determinan qué archivos se obtienen al iniciar sesión, lo que a su vez influye en cómo se inicializará el entorno. (variables, como estabas mencionando)
Andrew B
3
@ AndrewB Tienes razón ... También aprendí algo de esta pregunta. :)
Nathan C