Was ist der Vorteil, wenn Sie in ssh kein Terminal zuweisen?

66

Ab und zu mache ich sowas

ssh user@host sudo thing

und ich werde daran erinnert, dass ssh standardmäßig keine Pseudotty zuweist. Warum nicht? Welche Vorteile würde ich verlieren, wenn ich mich sshdarauf einlassen würde ssh -t?

Chas. Owens
quelle
1
> Ich werde daran erinnert, dass ssh kein pseudo-tty zuweist. Was passiert? Es würde die Frage bereichern, zu verstehen, wo das Problem liegt.
Air
5
@ Air Es gibt kein Problem, das ich beheben wollte. Bei der Implementierung von ssh gab es eine Auswahl, die ich zu verstehen versuchte. Die Frage ist sehr klar und die Antwort von Andrew B spricht die Frage gut an. Die Antwort kann wie ssh -tfolgt zusammengefasst werden: Laufen ist immer schlecht, weil es dazu führen kann, dass einige Befehle auf seltsame Weise unterbrochen werden. Wenn Sie dagegen einen Befehl ausführen, für den kein PTY erforderlich ist, wird die Fehlermeldung angezeigt, dass Sie ein Terminal benötigen.
Chas. Owens

Antworten:

73

Der Hauptunterschied ist das Konzept der Interaktivität . Es ähnelt dem Ausführen von Befehlen lokal innerhalb eines Skripts, anstatt sie selbst einzugeben. Der Unterschied besteht darin, dass ein Remote-Befehl eine Standardeinstellung auswählen muss und die nicht interaktive Funktion am sichersten ist. (und normalerweise am ehrlichsten)

STDIN

  • Wenn ein PTY zugewiesen ist, können Anwendungen dies erkennen und wissen, dass es sicher ist, den Benutzer zu zusätzlichen Eingaben aufzufordern, ohne dass dabei Probleme auftreten. Es gibt viele Programme, die den Schritt überspringen, den Benutzer zur Eingabe aufzufordern, wenn kein Terminal vorhanden ist, und das ist eine gute Sache. Es würde dazu führen, dass Skripte ansonsten unnötig hängen bleiben.
  • Ihre Eingabe wird für die Dauer des Befehls an den Remote-Server gesendet. Dies schließt Steuersequenzen ein. Während eine Ctrl-cUnterbrechung normalerweise dazu führt, dass eine Schleife des Befehls ssh sofort unterbrochen wird, werden Ihre Steuersequenzen stattdessen an den Remote-Server gesendet. Dies hat zur Folge, dass der Tastendruck "gehämmert" werden muss, um sicherzustellen, dass er eintrifft, wenn die Steuerung den Befehl ssh verlässt , jedoch bevor der nächste Befehl ssh beginnt.

Ich würde davor ssh -twarnen , in unbeaufsichtigten Skripten wie Crons zu verwenden. Eine nicht interaktive Shell, die einen Remote-Befehl auffordert, sich für Eingaben interaktiv zu verhalten, fordert alle Arten von Problemen an.

Sie können auch in Ihren eigenen Shell-Skripten prüfen, ob ein Terminal vorhanden ist. So testen Sie STDIN mit neueren Versionen von Bash:

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

STDOUT

  • Beim Aliasing sshauf ssh -tkönnen Sie einen zusätzlichen Zeilenumbruch in Ihren Zeilenenden erwarten. Es ist vielleicht nicht sichtbar für dich, aber es ist da; Es wird so ^Mangezeigt, als wäre es mit einer Leitung verbunden cat -e. Sie müssen dann zusätzliche Anstrengungen unternehmen, um sicherzustellen, dass dieser Steuercode Ihren Variablen nicht zugewiesen wird, insbesondere, wenn Sie diese Ausgabe in eine Datenbank einfügen.
  • Es besteht auch das Risiko, dass Programme davon ausgehen, dass sie Ausgaben rendern können, die für die Dateiumleitung nicht geeignet sind. Wenn Sie STDOUT in eine Datei umleiten, erkennt das Programm normalerweise, dass es sich bei STDOUT nicht um ein Terminal handelt, und lässt Farbcodes aus. Wenn die STDOUT-Umleitung von der Ausgabe des ssh-Clients stammt und dem Remote-Ende des Clients ein PTY zugeordnet ist, können die Remote-Programme keine solche Unterscheidung treffen, und Sie werden in Ihrer Ausgabedatei Terminal-Müll finden. Das Umleiten der Ausgabe in eine Datei auf dem Remote-Ende der Verbindung sollte weiterhin wie erwartet funktionieren.

Hier ist derselbe Bash-Test wie zuvor, jedoch für STDOUT:

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

Während es möglich ist, diese Probleme zu umgehen, werden Sie unweigerlich vergessen, Skripte um sie herum zu entwerfen. Wir alle tun es irgendwann. Möglicherweise merken Ihre Teammitglieder auch nicht, dass dieser Alias ​​vorhanden ist, was wiederum Probleme für Sie mit sich bringt, wenn sie Skripte schreiben, die Ihren Alias ​​verwenden.

Das Aliasing sshauf ssh -tist ein Fall, bei dem Sie gegen das Designprinzip der geringsten Überraschung verstoßen . Menschen werden auf Probleme stoßen, die sie nicht erwarten und möglicherweise nicht verstehen, was sie verursacht.

Andrew B
quelle
9
Man hat fast den Eindruck, dass ich in einem Team gearbeitet habe, das dies getan hat ...
Andrew B
In dem von dieser Antwort abgedeckten Bereich ist es großartig. Aber die Frage hatte einen größeren Umfang und wollte im Wesentlichen ALLE Unterschiede wissen (was zu erwarten ist). Zusätzliche Informationen: Auf der Prozessebene wird -t ZUERST ein tty zuweisen und DANN eine Shell ausführen (dabei / etc / profile und ~ / .bash_profile beziehen) und DANN den Befehl ausführen. Ohne -t erzeugt ssh STATT verschiedene env-Dateien (/etc/bash.bashrc, dann ~ / .bashrc) und führt DANN Ihren Befehl aus. Dies bedeutet, dass Sie in jedem sehr unterschiedliches Verhalten sehen können: kürzerer $ PATH, möglicherweise ein "unärer" Bash-Fehler, weil die von Ihnen angenommene ENV-
Variable
@Crossfit Wir haben das Thema Login-Shells vs. Non in den Kommentaren einer anderen Antwort behandelt, aber wir haben nicht auf eine erschöpfende Aufschlüsselung der Umweltunterschiede eingegangen, da das OP die beantwortete Frage bereits für ihre besonderen Bedürfnisse betrachtet hatte. Sie können gerne weitere Details hinzufügen, wo dies möglich ist, da dies möglicherweise anderen Personen bei der Beantwortung dieser Fragen und Antworten hilft.
Andrew B
33

SSH-Escapezeichen und Übertragung von Binärdateien

Ein Vorteil, der nicht in den anderen Antworten erwähnt worden ist , dass beim Betrieb ohne einen Pseudo-Terminal , die SSH - Escape - Zeichen , wie beispielsweise ~Cwerden nicht unterstützt ; Dies macht es für Programme sicher, Binärdateien zu übertragen, die diese Sequenzen enthalten können.

Konzeptioneller Beweiß

Kopieren Sie eine Binärdatei mit einem Pseudoterminal:

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

Kopieren Sie eine Binärdatei ohne Verwendung eines Pseudoterminals:

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

Die beiden Dateien sind nicht gleich:

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

Der mit einem Pseudoterminal kopierte ist beschädigt:

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

während der andere nicht ist:

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

Übertragen von Dateien über SSH

Dies ist besonders wichtig für Programme wie scpoder rsyncden SSH verwendet für die Datenübertragung. In dieser detaillierten Beschreibung der Funktionsweise des SCP-Protokolls wird erläutert, wie das SCP-Protokoll aus einer Mischung aus Textprotokollnachrichten und Binärdateidaten besteht.


OpenSSH schützt Sie vor sich selbst

Es ist erwähnenswert, dass -tder OpenSSH- sshClient die Zuweisung eines Pseudoterminals ablehnt, selbst wenn das Flag verwendet wird, wenn er feststellt, dass sein stdinStream kein Terminal ist:

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

Sie können den OpenSSH-Client weiterhin zwingen, ein Pseudoterminal zuzuweisen mit -tt:

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

In beiden Fällen ist es (vernünftigerweise) egal, ob stdoutoder stderrumgeleitet werden:

$ ssh -t anthony@remote_host 'echo $TERM' >| ssh_output
Connection to remote_host closed.
Anthony G - Gerechtigkeit für Monica
quelle
2
Das war ein sehr interessanter Punkt, über den ich nicht nachgedacht hatte. Danke, dass Sie diese Antwort hinzugefügt haben!
Jenny D
4

Auf dem Remote-Host haben wir mit dieser Einstellung zu tun:

/etc/sudoers
...
Defaults requiretty

Ohne Sudo

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

Und mit sudo

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

Mit sudo bekommen wir den zusätzlichen Wagenrücklauf

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

Die Lösung besteht darin, das Übersetzen der Zeilenumbrüche in Zeilenumbrüche mit zu deaktivierenstty -onlcr

$ ssh -t user@host stty -onlcr\; sudo echo -e 'foo\\nbar' | cat -e
foo$
    bar$
        Connection to localhost closed.
Christophe Morio
quelle
1
Schön, aber die Ausgabe ist eingerückt /: Weißt du zufällig, ob du sie automatisch mit einem Wagenrücklauf zurückgeben kannst (Unix-ähnlich)?
Boop
1

Denken Sie an die Abwärtskompatibilität.

Die beiden Hauptmodi von ssh sind interaktives Anmelden mit einem tty und angegebener Befehl ohne ein tty, da dies die genauen Funktionen von rloginbzw. rshwaren. ssh musste eine Obermenge von rlogin/ rshFeatures bereitstellen , um als Ersatz erfolgreich zu sein.

Die Vorgaben wurden also vor der Geburt von ssh festgelegt. Auf Kombinationen wie "Ich möchte einen Befehl angeben und ein tty erhalten" musste mit neuen Optionen zugegriffen werden. Seien Sie froh, dass wir zumindest diese Option jetzt haben, im Gegensatz zu damals rsh. Wir haben keine nützlichen Funktionen ausgetauscht, um verschlüsselte Verbindungen zu erhalten. Wir haben Bonusfunktionen!


quelle
0

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

Auf diese Weise können Sie eine Art "Shell" an den Remote-Server senden. Bei Servern, die keinen Shell-Zugriff gewähren, aber SSH zulassen (dh Github ist ein bekanntes Beispiel für SFTP-Zugriff), führt die Verwendung dieses Flags dazu, dass der Server Ihre Verbindung ablehnt.

Die Shell enthält auch alle Umgebungsvariablen (wie $PATH), sodass zum Ausführen von Skripten in der Regel ein Tty erforderlich ist.

Nathan C
quelle
1
Dies beantwortet die Frage nicht. Ich weiß bereits, wie man eine Pseudotty zuordnet. Ich möchte wissen, warum ich nicht immer eine zuweisen sollte.
Chas. Owens
1
@ Chas.Owens Denn, wie ich einig SSH - Server in der Antwort darauf hingewiesen , sich nicht tty Zugriff erlauben und es wird die Verbindung fallen , wenn Sie einen vom Server anfordern.
Nathan C
5
Ich denke, Sie könnten einige Ihrer Begriffe durcheinander bringen. Es ist keine Shell, nur weil ein PTY damit verbunden ist. Generell gibt es drei Arten von Shell: non-interactive, interactive, und login. loginist ein zusätzliches Merkmal der beiden anderen Schalentypen. Die Permutationen dieser drei bestimmen, welche Dateien bei der Anmeldung bezogen werden, was wiederum Einfluss darauf hat, wie die Umgebung initialisiert wird. (Variablen, wie Sie erwähnt haben)
Andrew B
3
@ AndrewB Du hast Recht ... Ich habe auch etwas aus dieser Frage gelernt. :)
Nathan C