Quel est l'avantage de ne pas allouer de terminal en ssh?

66

De temps en temps je ferai quelque chose comme

ssh user@host sudo thing

et on me rappelle que ssh n'alloue pas de pseudo-tty par défaut. Pourquoi pas Quels avantages serais - je perdre si j'Aliased sshà ssh -t?

Chas. Owens
la source
1
> On me rappelle que ssh n'alloue pas de psuedo-tty. Que se passe-t-il? Cela enrichirait la question de comprendre quel est le problème.
Air
5
@Air Il n'y a pas un problème que j'essayais de résoudre. J'avais essayé de comprendre comment SSH était implémenté. La question est très claire et la réponse d’Andrew B répond bien à la question. La réponse peut être résumée ainsi: courir ssh -ttoujours est mauvais parce que certaines commandes peuvent se briser de manière étrange. Tandis que l'exécution d'une commande nécessitant un PTY sans aucun résultat génère un message d'erreur indiquant que vous avez besoin d'un terminal.
Chas. Owens

Réponses:

73

La principale différence est le concept d' interactivité . Cela ressemble à l'exécution de commandes localement dans un script, par opposition à leur saisie par vous-même. C'est différent en ce sens qu'une commande à distance doit choisir une valeur par défaut et que la non-interactive est la plus sûre. (et généralement le plus honnête)

STDIN

  • Si un PTY est alloué, les applications peuvent le détecter et savoir qu’il est prudent d’inviter l’utilisateur à fournir des informations supplémentaires sans casser des choses. Il existe de nombreux programmes qui ignorent l'étape consistant à inviter l'utilisateur à entrer si aucun terminal n'est présent, et c'est une bonne chose. Sinon, les scripts se bloqueraient inutilement.
  • Votre entrée sera envoyée au serveur distant pour la durée de la commande. Cela inclut les séquences de contrôle. Alors qu'une Ctrl-cpause provoquerait normalement la rupture immédiate d'une boucle de la commande ssh, vos séquences de contrôle seront plutôt envoyées au serveur distant. Cela entraîne la nécessité de "marteler" la frappe afin de s'assurer qu'elle arrive lorsque le contrôle quitte la commande ssh, mais avant le début de la commande ssh suivante.

Je vous ssh -tdéconseille d' utiliser des scripts non surveillés, tels que crons. Un shell non interactif demandant à une commande distante de se comporter de manière interactive pour une entrée est une source de problèmes.

Vous pouvez également tester la présence d'un terminal dans vos propres scripts shell. Pour tester STDIN avec les nouvelles versions de bash:

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

STDOUT

  • Lorsque vous aliasez sshsur ssh -t, vous pouvez vous attendre à obtenir un retour chariot supplémentaire à la fin de votre ligne. Ce n'est peut-être pas visible pour vous, mais c'est là; il apparaîtra comme ^Mlorsqu'il est connecté à cat -e. Vous devez ensuite déployer tous les efforts supplémentaires pour vous assurer que ce code de contrôle n'est pas affecté à vos variables, en particulier si vous allez insérer cette sortie dans une base de données.
  • Il y a également le risque que les programmes supposent qu'ils peuvent rendre une sortie qui n'est pas conviviale pour la redirection de fichier. Normalement, si vous redirigiez STDOUT vers un fichier, le programme reconnaîtrait que votre STDOUT n'est pas un terminal et omettra les codes de couleur. Si la redirection STDOUT provient de la sortie du client ssh et qu'un PTY est associé à l'extrémité distante du client, les programmes distants ne peuvent pas faire une telle distinction et vous allez vous retrouver avec des ordures dans votre fichier de sortie. La redirection de la sortie vers un fichier situé à l' extrémité distante de la connexion doit toujours fonctionner comme prévu.

Voici le même test bash que précédemment, mais pour STDOUT:

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

Bien qu'il soit possible de contourner ces problèmes, vous allez inévitablement oublier de concevoir des scripts autour de ces problèmes. Nous le faisons tous à un moment donné. Les membres de l' équipe peuvent également ne pas se rendre compte / se rappeler que cet alias est en place, qui à son tour créer des problèmes pour vous quand ils écrivent des scripts qui utilisent votre alias.

Le pseudonyme sshde ssh -test un cas où vous violerez le principe de conception de la moindre surprise . les gens rencontreront des problèmes auxquels ils ne s'attendent pas et peuvent ne pas comprendre ce qui les cause.

Andrew B
la source
9
On a presque l'impression d'avoir travaillé dans une équipe qui a fait cela ...
Andrew B
À la portée couverte par cette réponse, c'est un super. Mais la question avait une portée plus large, voulant essentiellement connaître TOUTES les différences (à quoi s'attendre). Informations supplémentaires: Au niveau du processus, -t allouera FIRST un tty, puis exécutera un shell (en cours de chemin, en recherchant / etc / profile et ~ / .bash_profile), puis ENSUIVANT la commande. Sans -t, ssh INSTEAD générera différents fichiers env (/etc/bash.bashrc, puis ~ / .bashrc), puis EXÉCUTERA votre commande. Cela signifie que vous pouvez voir des comportements très différents dans chacun: $ PATH plus court, peut-être une erreur 'unary' bash parce que la variable ENV que vous supposez ne s'y trouve pas ...
Scott Prive
@Crossfit Nous avons abordé le sujet des coquilles de connexion par rapport aux non dans les commentaires d'une autre réponse, mais nous n'avons pas détaillé les différences environnementales car le PO avait déjà examiné la question pour répondre à ses besoins particuliers. S'il vous plaît, n'hésitez pas à ajouter des détails là où vous voyez la possibilité de le faire, car cela pourrait aider d'autres personnes qui tombent sur cette question / réponse
Andrew B
33

Caractères d'échappement SSH et transfert de fichiers binaires

Un autre avantage qui n’a pas été mentionné dans les autres réponses est que, lorsqu’ils fonctionnent sans pseudo-terminal , les caractères d’échappement SSH tels que ne~C sont pas pris en charge ; Cela permet aux programmes de transférer des fichiers binaires pouvant contenir ces séquences en toute sécurité.

Preuve de concept

Copier un fichier binaire en utilisant un pseudo-terminal:

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

Copier un fichier binaire sans utiliser de pseudo-terminal:

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

Les deux fichiers ne sont pas identiques:

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

Celui qui a été copié avec un pseudo-terminal est corrompu:

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

tandis que l'autre n'est pas:

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

Transfert de fichiers sur SSH

Ceci est particulièrement important pour les programmes tels que scpou rsyncutilisant SSH pour le transfert de données. Cette description détaillée du fonctionnement du protocole SCP explique en quoi celui-ci consiste en un mélange de messages de protocole textuels et de données de fichier binaires.


OpenSSH vous aide à vous protéger de vous-même

Il est à noter que même si l' -tindicateur est utilisé, le sshclient OpenSSH refusera d'allouer un pseudo-terminal s'il détecte que son stdinflux n'est pas un terminal:

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

Vous pouvez toujours forcer le client OpenSSH à allouer un pseudo-terminal avec -tt:

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

Dans les deux cas, peu importe la raison (sensuellement) stdoutou stderrsont redirigés:

$ ssh -t anthony@remote_host 'echo $TERM' >| ssh_output
Connection to remote_host closed.
Anthony G - justice pour Monica
la source
2
C'était un point très intéressant que je n'avais pas pris en compte, merci d'avoir ajouté cette réponse!
Jenny D dit réintégrer Monica le
4

Sur l'hôte distant, nous devons faire avec ce paramètre:

/etc/sudoers
...
Defaults requiretty

Sans sudo

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

Et avec sudo

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

Avec sudo nous obtenons le retour supplémentaire

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

La solution consiste à désactiver la nouvelle ligne à traduire en chariot retour-nouvelle ligne avecstty -onlcr

$ ssh -t user@host stty -onlcr\; sudo echo -e 'foo\\nbar' | cat -e
foo$
    bar$
        Connection to localhost closed.
Christophe Morio
la source
1
Bien, mais la sortie est en retrait /: Est-ce que vous savez si vous pouvez le renvoyer automatiquement (genre Unix)?
Boop
1

Pensez à la compatibilité ascendante.

Les 2 modes principaux de ssh sont: login-interactive avec tty et commande-spécifiée sans tty, car c’étaient les capacités exactes de rloginet rshrespectivement. SSH devait fournir un sur-ensemble de rlogin/ rshfonctionnalités pour réussir son remplacement.

Donc, les valeurs par défaut ont été décidées avant la naissance de ssh. Des combinaisons telles que "Je veux spécifier une commande et obtenir un tty" devaient être accessibles avec de nouvelles options. Soyez heureux qu'au moins nous ayons cette option maintenant, contrairement à ce que nous utilisions rsh. Nous n'avons échangé aucune fonctionnalité utile pour obtenir des connexions cryptées. Nous avons des bonus!


la source
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.

Cela vous permet d’obtenir un "shell" sur le serveur distant. Pour les serveurs qui n'accordent pas d' accès shell mais autorisent SSH (Github est un exemple connu d'accès SFTP), l'utilisation de cet indicateur entraîne le rejet de votre connexion par le serveur.

Le shell contient également toutes vos variables d'environnement (comme $PATH), de sorte que l'exécution de scripts nécessite généralement l'utilisation d'un terminal.

Nathan C
la source
1
Cela ne répond pas à la question. Je sais déjà comment allouer un pseudo-tty. Je veux savoir pourquoi je ne devrais pas toujours en attribuer un.
Chas. Owens
1
@ Chas.Owens Parce que, comme je l’ai souligné dans la réponse, certains serveurs SSH n’autorisent pas l’ accès au tty et la connexion sera coupée si vous en demandez une au serveur.
Nathan C
5
Je pense que vous êtes peut-être en train de confondre une partie de votre terminologie. Ce n'est pas un shell simplement parce qu'un PTY y est associé. Il y a généralement trois types de coque: non-interactive, interactiveet login. loginest une caractéristique supplémentaire des deux autres types de coque. Les permutations de ces trois fichiers déterminent quels fichiers sont générés lors de la connexion, ce qui influence à son tour la façon dont l'environnement sera initialisé. (variables, comme vous l'avez mentionné)
Andrew B
3
@ AndrewB Vous avez raison ... J'ai aussi appris quelque chose de cette question. :)
Nathan C