web-dev-qa-db-fra.com

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

De temps en temps je ferai quelque chose comme

ssh user@Host Sudo thing

et je me souviens que ssh n'alloue pas de pseudo-tty par défaut. Pourquoi pas? Quels avantages perdrais-je si j'aliasais ssh à ssh -t?

68
Chas. Owens

La principale différence est le concept d'interactivité . C'est similaire à exécuter des commandes localement à l'intérieur d'un script, par rapport à les taper vous-même. C'est différent car une commande à distance doit choisir une valeur par défaut, et 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 sûr de demander à l'utilisateur une entrée supplémentaire sans casser les choses. Il existe de nombreux programmes qui ignoreront l'étape d'inviter l'utilisateur à entrer s'il n'y a pas de terminal présent, et c'est une bonne chose. Sinon, les scripts se bloqueraient inutilement.
  • Votre entrée sera envoyée au serveur distant pendant la durée de la commande. Cela inclut les séquences de contrôle. Alors qu'un Ctrl-c break entraînerait 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. Il en résulte un besoin de "marteler" la frappe pour 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 déconseille d'utiliser ssh -t dans des scripts sans assistance, tels que crons. Un shell non interactif demandant à une commande distante de se comporter de manière interactive pour la saisie demande toutes sortes de problèmes.

Vous pouvez également tester la présence d'un terminal dans vos propres scripts Shell. Pour tester STDIN avec des versions plus récentes de bash:

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

STDOUT

  • Lors de l'aliasing de ssh vers ssh -t, vous pouvez vous attendre à obtenir un retour chariot supplémentaire à la fin de votre ligne. Elle n'est peut-être pas visible pour vous, mais elle est là; il apparaîtra comme ^M lorsqu'il est redirigé vers cat -e. Vous devez ensuite déployer des 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 existe également le risque que les programmes supposent qu'ils peuvent rendre une sortie qui n'est pas adaptée à la redirection de fichiers. Normalement, si vous deviez rediriger STDOUT vers un fichier, le programme reconnaîtrait que votre STDOUT n'est pas un terminal et omettrait tout code couleur. Si la redirection STDOUT provient de la sortie du client ssh et qu'il y a un PTY associé à l'extrémité distante du client, les programmes distants ne peuvent pas faire une telle distinction et vous vous retrouverez avec des déchets terminaux dans votre fichier de sortie. La redirection de la sortie vers un fichier à l'extrémité distante de la connexion devrait 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 d'eux. Nous le faisons tous à un moment donné. Les membres de votre équipe peuvent également ne pas réaliser/se rappeler que cet alias est en place, ce qui, à son tour, vous posera des problèmes lorsque ils écrivent des scripts qui utilisent votre alias .

Alias ​​ssh vers ssh -t est vraiment 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.

73
Andrew B

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

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

Preuve de concept

Copiez un fichier binaire à l'aide d'un pseudo-terminal:

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

Copiez 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 via SSH

Ceci est particulièrement important pour des programmes tels que scp ou rsync qui utilisent SSH pour le transfert de données. Ceci description détaillée du fonctionnement du protocole SCP explique comment le protocole SCP consiste en un mélange de messages de protocole textuels et de données de fichiers binaires.


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

Il convient de noter que même si le -t est utilisé, le client OpenSSH ssh refusera d'allouer un pseudo-terminal s'il détecte que son flux stdin 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, cela (sensiblement) ne se soucie pas si stdout ou stderr sont redirigés:

$ ssh -t anthony@remote_Host 'echo $TERM' >| ssh_output
Connection to remote_Host closed.
34
Anthony Geoghegan

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 chariot 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 le traduire la nouvelle ligne en chariot retour-nouvelle ligne avec stty -onlcr

$ ssh -t user@Host stty -onlcr\; Sudo echo -e 'foo\\nbar' | cat -e
foo$
    bar$
        Connection to localhost closed.
4
Christophe Morio

Pensez à la compatibilité descendante.

Les 2 modes principaux de ssh sont la connexion interactive avec un tty et la commande spécifiée sans tty, car ce sont les capacités exactes de rlogin et rsh respectivement. ssh devait fournir un surensemble de fonctionnalités rlogin/rsh pour réussir le remplacement.

Les valeurs par défaut ont donc été décidées avant la naissance de ssh. Des combinaisons comme "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 pas échangé de fonctionnalités utiles pour obtenir des connexions cryptées. Nous avons des bonus!

1
user193597

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 une sorte de "Shell" sur le serveur distant. Pour les serveurs qui pas accordent l'accès Shell mais autorisent SSH (c'est-à-dire que Github est un exemple connu d'accès SFTP), l'utilisation de cet indicateur entraînera le serveur à rejeter votre connexion.

Le Shell a également toutes vos variables environnementales (comme $PATH) donc l'exécution de scripts a généralement besoin d'un tty pour fonctionner.

0
Nathan C