Verwirrt über die Docker-t-Option zum Zuweisen eines Pseudo-TTY


204

Was genau macht diese Option? Ich habe viel über TTY gelesen und bin immer noch verwirrt. Ich habe damit herumgespielt, dass ich nicht das -tund nur habe, -iund es scheint, als würden Programme, die Benutzereingaben erwarten, einen Fehler ohne das auslösen -t. Warum ist es wichtig, dass Pseudo-TTY aktiviert ist?

Antworten:


222

Die -tOption zeigt an, wie Unix / Linux den Terminalzugriff behandelt. In der Vergangenheit war ein Terminal eine Hardline-Verbindung, später eine modembasierte Verbindung. Diese hatten physische Gerätetreiber (sie waren echte Ausrüstungsgegenstände). Nach der Verwendung verallgemeinerter Netzwerke wurde ein Pseudo-Terminal-Treiber entwickelt. Dies liegt daran, dass eine Trennung zwischen dem Verständnis, welche Terminalfunktionen verwendet werden können, entsteht, ohne dass diese direkt in Ihr Programm geschrieben werden müssen (siehe Manpages auf stty, curses).

Führen Sie vor diesem Hintergrund einen Container ohne Optionen aus, und standardmäßig haben Sie einen Standard-Stream ( docker run | <cmd>funktioniert also). Wenn Sie mit ausführen -i, wird der <cmd> | docker run -iStandard- Stream hinzugefügt ( funktioniert also). Verwenden Sie diese Option -tnormalerweise in der Kombination, -itund Sie haben einen Terminaltreiber hinzugefügt. Wenn Sie mit dem Prozess interagieren, ist dies wahrscheinlich das, was Sie möchten. Grundsätzlich sieht der Container-Start wie eine Terminalverbindungssitzung aus.


7
Dies sollte die beste Antwort sein. Obwohl es hier nicht das technischste ist, erklärt es das grundlegende Verhalten der -itFlags.
Kris Khaira

1
Stimme Kris zu. Ich las die anderen Antworten und war immer noch total verwirrt. Diese Antwort klärt es auf.
Ben Lee

3
Ja, es ist vielleicht erwähnenswert, dass "TTY" selbst ein Akronym ist, das vom Wort "Teletypewriter" (AKA "Teleprinter") stammt. Dies war ein Gerätename, mit dem Sie Text eingeben und gleichzeitig versenden können - wie bei einem Telefon für Text ;-) Versuchen Sie docker run -i ubuntuund docker run -it ubuntuSie werden den Unterschied sofort sehen. Mit "-i" können Sie den Container so einstellen, dass er auf die Interaktion vom Host wartet. Die tatsächliche Interaktion von der Konsole (Terminal) ist jedoch möglich, nachdem Sie den tty-Treiber mit dem Flag "-t" "zugewiesen" haben.
Zegar

Kann ich tty im Docker starten? Ich habe eine App, die nicht mehr funktioniert, mit der ich den Docker nicht ausführe -t, aber ich kann den Docker-Startbefehl in der Produktion nicht ändern. Also muss ich die App denken lassen, dass sie gestartet wurde -t.
Mvorisek

96

Späte Antwort, könnte aber jemandem helfen

docker run/exec -iverbindet die STDIN des Befehls im Container mit der STDIN des docker run/execselbst.

So

  • docker run -i alpine catgibt Ihnen eine leere Zeile, die auf Eingabe wartet. Geben Sie "Hallo" ein, Sie erhalten ein Echo "Hallo". Der Container wird erst beendet, wenn Sie CTRL+ senden, Dda der Hauptprozess catauf die Eingabe aus dem unendlichen Stream wartet, der die Terminaleingabe des ist docker run.
  • Auf der anderen Seite echo "hello" | docker run -i alpine catwird "Hallo" gedruckt und sofort beendet, da catbemerkt wird, dass der Eingabestream beendet wurde und sich selbst beendet.

Wenn Sie versuchen, docker psnachdem Sie einen der oben genannten Schritte beendet haben, werden Sie keine laufenden Container finden. In beiden Fällen hat sich catselbst beendet, so dass Docker den Container beendet hat.

Für "-t" teilt dies dem Hauptprozess im Docker mit, dass seine Eingabe ein Endgerät ist.

So

  • docker run -t alpine catgibt Ihnen eine leere Zeile, aber wenn Sie versuchen, "Hallo" einzugeben, erhalten Sie kein Echo. Dies liegt daran cat, dass dieser Eingang zwar mit einem Klemmeneingang verbunden ist, jedoch nicht mit Ihrem Eingang. Das "Hallo", das Sie eingegeben haben, hat die Eingabe von nicht erreicht cat. catwartet auf Eingaben, die nie eintreffen.
  • echo "hello" | docker run -t alpine catgibt Ihnen auch eine leere Zeile und verlässt den Container nicht weiter CTRL- Daber Sie erhalten kein Echo "Hallo", weil Sie nicht bestanden haben-i

Wenn Sie CTRL+ senden C, erhalten Sie Ihre Shell zurück. Wenn Sie es docker psjetzt versuchen , wird der catContainer weiterhin ausgeführt. Dies liegt daran, dass catimmer noch auf einen Eingabestream gewartet wird, der nie geschlossen wurde. Ich habe keine nützliche Verwendung für mich -tallein gefunden, ohne mit kombiniert zu werden -i.

Nun zu -itzusammen. Dies teilt cat mit, dass sein Eingang ein Terminal ist, und verbindet gleichzeitig dieses Terminal mit dessen Eingang docker runein Terminal ist. docker run/execwird sicherstellen, dass seine eigene Eingabe tatsächlich ein tty ist, bevor sie an übergeben wird cat. Aus diesem Grund erhalten Sie eine, input device is not a TTYwenn Sie es versuchen, echo "hello" | docker run -it alpine catda in diesem Fall die Eingabe von sich docker runselbst die Pipe des vorherigen Echos ist und nicht das Terminal, an dem sie docker runausgeführt wird

Schließlich, warum sollten Sie bestehen müssen, -twenn -iSie den Trick tun, Ihre Eingabe mit catder Eingabe zu verbinden? Dies liegt daran, dass Befehle die Eingabe anders behandeln, wenn es sich um ein Terminal handelt. Dies lässt sich auch am besten anhand eines Beispiels veranschaulichen

  • docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -u root -pgibt Ihnen eine Passwortabfrage. Wenn Sie das Passwort eingeben, werden die Zeichen sichtbar gedruckt.
  • docker run -i alpine shgibt Ihnen eine leere Zeile. Wenn Sie einen Befehl lseingeben, wie Sie eine Ausgabe erhalten, erhalten Sie jedoch keine Eingabeaufforderung oder farbige Ausgabe.

In den letzten beiden Fällen Sie dieses Verhalten, weil mysqlauch shellnicht der Eingang als tty Behandlung und somit nicht tty spezifisches Verhalten wie die Eingangs Maskierung oder die Ausgabe verwendet haben Färbung.


6
Die beste Antwort hier, die mich wirklich verstehen lässt, was genau -tund welche -iOptionen es gibt!
Ruslan Stelmachenko

1
Fantastische Antwort, die jede meiner Fragen vorwegnahm
James Machin

@ Ahmed Ghonim, sehr gute Antworten. Danke dir. Aber zu "Dies liegt daran, dass Befehle die Eingabe anders behandeln, wenn es sich um ein Terminal handelt" denke ich, dass dies eine falsche Eingabe ist, oder? Es sollte "Dies liegt daran, dass Befehle die Eingabe anders behandeln, wenn es sich nicht um ein Terminal handelt", richtig?
4.

@ Ahmed Ghonim. Kristallklar. Aber was ist mit Docker Run -a = stdin Alpenkatze?
HKIT

1
@HKIIT "-a = stdin" hängt den stdin-Stream an den Container an, jedoch ohne Speicherzuordnung. Es ist das Flag -i, das den Pufferspeicher im Container für den stdin-Stream zuweist, daher die Beschreibung "STDIN offen lassen, auch wenn es nicht angehängt ist", wenn -i übergeben wird, wird der Speicher für stdin unabhängig von den Anhangsflags zugewiesen. Ohne diesen zugewiesenen Speicher sind die Lesevorgänge für stdin leer / eof. Außerdem müssen Sie "-a = stdout" einfügen, um die Antwort des Befehls cat zu sehen, zum Beispiel: "docker run -i -a = stdin -a = stdout alpine cat" ... natürlich müssen Sie dies nicht tun Führen Sie einfach "docker run -i alpine cat" aus.
David D

71

-tLaut einer Google-Suche ist das Argument NICHT gut dokumentiert oder wird von vielen Menschen häufig erwähnt.

Es wird nicht einmal angezeigt, wenn Sie eine Liste aller Docker-Client-Argumente anzeigen (was sollte das sein), indem Sie dockeran der Bash-Eingabeaufforderung (mit der neuesten Version von 1.8.1) eingeben .

In der Tat, wenn Sie versuchen, spezifische Hilfe zu diesem Argument zu erhalten, indem Sie tippen, docker -t --helpwenn dies diese erstaunlich vage Antwort gibt:

Flag bereitgestellt, aber nicht definiert: -t

Sie können also nicht dafür verantwortlich gemacht werden, dass Sie über dieses Argument verwirrt sind!

In der Docker-Online-Dokumentation wird erwähnt, dass "Pseudo-tty zuweisen" verwendet wird und häufig verwendet wird mit -i:

https://docs.docker.com/reference/run/

Ich habe gesehen, dass es in der Dokumentation für den großartigen jwilder/nginx-proxyDocker-Container folgendermaßen verwendet wurde:

docker run -d -p 80:80 --name nginx -v /tmp/nginx:/etc/nginx/conf.d -t nginx

In diesem Fall wird die Ausgabe an die 'virtuelle' tty (Bash-Eingabeaufforderung / Terminal) in diesem Docker-Container gesendet. Anschließend können Sie diese Ausgabe sehen , indem Sie den Docker Befehl ausgeführt wird, docker logs CONTAINERwo CONTAINERdas erste Paar der Zeichen dieses Behälters ID ist. Diese CONTAINER-ID kann durch Eingabe ermittelt werdendocker ps -a

Ich habe dieses -tArgument kurz im folgenden Link erwähnt gesehen, wo es steht

Die Flags -tund -iweisen ein Pseudo-tty zu und halten stdin offen, auch wenn es nicht angehängt ist. Auf diese Weise können Sie den Container wie eine herkömmliche VM verwenden, solange die Bash-Eingabeaufforderung ausgeführt wird.

https://coreos.com/os/docs/latest/getting-started-with-docker.html

Ich hoffe das hilft! Ich bin mir nicht sicher, warum dies nicht viel dokumentiert oder verwendet wird. Vielleicht ist es experimentell und wird in kommenden Versionen als dokumentierte Funktion implementiert.


21
Die Dokumentation erscheint für docker run --help, nicht docker -t --help: -t, --tty=false Allocate a pseudo-TTY"
bskaggs

5

Was ich über die weiß -t ist Folgendes:

docker exec -ti CONTAINER bash- erlaubt mir, mich im Container "einzuloggen". Es fühlt sich an wie ssh-ing (es ist nicht).

Das Problem war jedoch, als ich eine Datenbank wiederherstellen wollte.

Normalerweise tue ich dasdocker exec -ti mysql.5.7 mysql - Hier führe ich den Befehl mysql im Container aus und erhalte ein interaktives Terminal.

Ich habe <dump.sqlzum vorherigen Befehl hinzugefügt , damit ich eine Datenbank wiederherstellen kann. Aber es ist gescheitert mitcannot enable tty mode on non tty input .

Entfernen der -tgeholfenen. Ich verstehe immer noch nicht warum:

docker exec -i mysql.5.7 mysql < dump.sql

Der letzte funktioniert. Hoffe das hilft den Menschen.


Kann ich tty im Docker starten? Ich habe eine App, die nicht mehr funktioniert, mit der ich den Docker nicht ausführe -t, aber ich kann den Docker-Startbefehl in der Produktion nicht ändern. Also muss ich die App denken lassen, dass sie gestartet wurde -t.
Mvorisek

1

Wenn Sie unter Linux einen Befehl ausführen, benötigen Sie ein Terminal (tty), um ihn auszuführen.

Wenn Sie also eine Verbindung zum Docker herstellen möchten (oder einen Befehl im Docker-Container ausführen möchten), müssen Sie die Option -t angeben, die die Berücksichtigung des Terminals im Docker-Container berücksichtigt.


0

Jeder Prozess hat drei Datenströme, dh STDIN/ STDOUT/ STDERR. Wenn ein Prozess in einem Container ausgeführt wird, ist das Terminal standardmäßig mit dem STDOUT-Stream des im Container ausgeführten Prozesses verbunden. Daher sind alle Ausgabestreams sichtbar, während der docker runBefehl im Terminal ausgeführt wird. Wenn Sie jedoch Eingaben für den laufenden Prozess im Container bereitstellen möchten, müssen Sie eine Verbindung mit dem STDIN-Kanal des Prozesses herstellen, der nicht standardmäßig ist und mit dem docker run -iBefehl ausgeführt wird.

-t wird für interaktive / formatierte Eingabevorgänge verwendet.


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.