De temps en temps, je vais faire quelque chose comme
ssh user@host sudo thing
et on me rappelle que ssh n'alloue pas de pseudo-tty par défaut. Pourquoi ne le fait-il pas ? Quels avantages perdrais-je si j'aliasais ssh
a ssh -t
?
De temps en temps, je vais faire quelque chose comme
ssh user@host sudo thing
et on me rappelle que ssh n'alloue pas de pseudo-tty par défaut. Pourquoi ne le fait-il pas ? Quels avantages perdrais-je si j'aliasais ssh
a ssh -t
?
La principale différence réside dans le concept de interactivité . Cela revient à exécuter des commandes localement à l'intérieur d'un script, plutôt que de les taper vous-même. C'est différent dans le sens où une commande à distance doit choisir un défaut, et le non-interactif est le plus sûr. (et généralement le plus honnête)
Ctrl-c
break devrait normalement provoquer la rupture immédiate d'une boucle sur la commande ssh, vos séquences de contrôle seront au contraire envoyées au serveur distant. Il est donc nécessaire de " marteler " la frappe pour s'assurer qu'elle arrive au moment où la commande feuilles la commande ssh, mais avant que la commande ssh suivante ne commence.Je vous déconseille d'utiliser ssh -t
dans les scripts non surveillés, comme les crons. Un scripts non interactif demandant à une commande distante de se comporter de manière interactive pour l'entrée est en train de demander toutes sortes de problèmes.
Vous pouvez également tester la présence d'un terminal dans vos propres Shell Shell. Pour tester STDIN avec des versions plus récentes de bash :
# fd 0 is STDIN
[ -t 0 ]; echo $?
ssh
a ssh -t
vous pouvez vous attendre à obtenir un retour chariot supplémentaire dans vos fins de ligne. Il n'est peut-être pas visible pour vous, mais il est là ; il apparaîtra sous la forme suivante ^M
lorsqu'il est acheminé vers cat -e
. Vous devez alors faire l'effort supplémentaire de veiller à ce que ce code de contrôle ne soit pas affecté à vos variables, en particulier si vous devez insérer cette sortie dans une base de données.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 ou à un autre. Il se peut également que les membres de votre équipe ne réalisent pas/ne se souviennent pas que cet alias est en place, ce qui, à son tour, vous créera des problèmes lorsque ils écrire des scripts qui utilisent votre alias.
Aliasing ssh
a ssh -t
est un cas où vous allez violer le principe de conception de moindre surprise ; les gens rencontreront des problèmes auxquels ils ne s'attendent pas et ne comprendront peut-être pas ce qui les cause.
Un avantage qui n'a pas été mentionné dans les autres réponses est que lors de l'exploitation sans pseudo-terminal le SSH caractères d'échappement comme ~C
sont non supporté ; cela permet aux programmes de transférer en toute sécurité des fichiers binaires qui peuvent contenir ces caractères de contrôle et d'autres.
Sans pseudo-terminal, les caractères sont transférés à l'hôte distant "tels quels" :
$ printf "one\ntwo\n~Cthree\n" | ssh user@host tee 1
one
two
~Cthree
Si vous essayez de forcer l'allocation d'un pseudo-terminal, l'inclusion de l'élément ~C
provoque le ssh>
l'invite à imprimer pour permettre à l'utilisateur de saisir une commande SSH, en interrompant le transfert.
$ printf "one\ntwo\n~Cthree\n" | ssh -tt user@host tee 2
ssh>
one
two
three
one
two
three
A ~.
est pire car il n'y a pas de transfert de données :
$ printf "one\ntwo\n~.three\n" | ssh -tt user@host tee 2
Connection to host closed.
Les caractères de contrôle de flux du logiciel (XON/XOFF) peuvent également être traités de manière spéciale lorsqu'un pseudo-terminal est alloué.
$ printf "one\ntwo\n^Sthree\n" | ssh user@host tee 1
one
two
three
$ ssh user@host cat -vet 1
one$
two$
^Sthree$
Avec un pseudo-terminal, le Ctrl-S
est interprété comme un signal de pause du flux d'entrée, de sorte qu'aucune donnée ne peut plus être envoyée après avoir rencontré ce caractère (à moins qu'il ne soit suivi d'un caractère Ctrl-Q
plus tard dans le flux d'entrée).
Dans ce cas, le fait de forcer l'allocation d'un pseudo-terminal fait que le fichier de l'extrémité distante est vide.
$ printf "one\ntwo\n^Sthree\n" | ssh -tt user@host tee 2
one
two
Dans ce cas, le fait de forcer l'allocation d'un pseudo-terminal fait que le fichier à l'extrémité distante contient les trois lignes mais sans les caractères de contrôle :
$ printf "one\ntwo\n^Sthree^Q\n" | ssh -tt user@host tee 2
one
two
three
one
two
three
$ ssh user@host cat -vet 2
one$
two$
three$
Avec un pseudo-terminal, les caractères de saut de ligne (décimal 10, hexa 0A
en ASCII) sont également traduits en CRLF
séquences (hex 0D0A
en ASCII) .
A partir de l'exemple précédent :
$ ssh -t user@host cat 1 | cat -vet
one^M$
two^M$
^Sthree^M$
Connection to host closed.
$ 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 les mêmes :
$ 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
alors que l'autre ne l'est pas :
$ ./free2
total used free shared buffers cached
Mem: 2065496 1980876 84620 0 48264 1502444
-/+ buffers/cache: 430168 1635328
Swap: 4128760 112 4128648
Ceci est particulièrement important pour les programmes tels que scp
o rsync
qui utilisent SSH pour le transfert de données. Ce site 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.
Il est intéressant de noter que même si le -t
est utilisé, l'option OpenSSH ssh
Le client refusera d'allouer un pseudo-terminal s'il détecte que son stdin
stream 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, il ne se soucie pas (raisonnablement) de savoir si stdout
o stderr
sont redirigés :
$ ssh -t anthony@remote_host 'echo $TERM' >| ssh_output
Connection to remote_host closed.
Sur l'hôte distant, nous devons nous occuper de 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, on obtient 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 traduit le saut de ligne en retour de chariot-saut de ligne con stty -onlcr
$ ssh -t user@host stty -onlcr\; sudo echo -e 'foo\\nbar' | cat -e
foo$
bar$
Connection to localhost closed.
Pensez à la rétrocompatibilité.
Les deux principaux modes de ssh sont l'ouverture de session interactive avec un pty, et la commande spécifiée sans pty, parce que c'étaient les capacités exactes de rlogin
y rsh
respectivement. ssh devait fournir un sur-ensemble de rlogin
/ rsh
caractéristiques pour réussir en tant que 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 y Il fallait accéder à "get a pty" avec de nouvelles options. Soyez heureux qu'au moins nous ont cette option maintenant, contrairement à l'époque où nous utilisions rsh
. Nous n'avons pas renoncé à des fonctions utiles pour obtenir des connexions cryptées. Nous avons obtenu des fonctionnalités supplémentaires !
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 font pas accorder l'accès à Shell mais autoriser SSH (c'est-à-dire que Github est un exemple connu d'accès SFTP), l'utilisation de cet indicateur entraînera le rejet de votre connexion par le serveur.
Le Shell contient également toutes vos variables d'environnement (telles que $PATH
) donc l'exécution de scripts nécessite généralement un tty pour fonctionner.
SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.