wake-up-neo.com

Docker Anzahl der Zeilen im Terminal, die sich im Docker ändern

Ich würde gerne wissen, wie man das folgende Verhalten ändert. Sagen wir, mein Terminal hat 28 Zeilen. Dann benutze ich die folgenden Befehle:

$ tput lines # my terminal
28
$ docker run  --rm  -it ubuntu:16.04 tput lines  # docker container
24  ## WHY??
$ docker run  --rm  -it ubuntu:16.04 bash # docker container inside command
[email protected]:/# tput lines
28

Wie Sie sehen, auch wenn alle Ergebnisse 28 sein sollen, wenn ich den Container als docker run --rm -it ubuntu:16.04 tput linese anrufe, gibt es mir trotz der Größe meines Terminals immer 24. Dies ist nicht nur mit dem Ubuntu-Container, ich habe es auch mit debian (docker run --rm -it debian tput lines) versucht und ich habe das gleiche Ergebnis 24.

Der Zweck besteht darin, das MDP-Präsentationswerkzeug zu verwenden, das die Leitungen in Ihrem Terminal berücksichtigt. Als meine Implementierung fehlgeschlagen ist, habe ich die Docker-Implementierung einer anderen Person ausprobiert, aber ich habe den gleichen Fehler erhalten.

Hier ist mein Fehler in einem Bild:

Docker number of lines in terminal changing inside docker

Hat jemand eine Idee, was es sein könnte und wie kann dies gelöst werden?

32
silgon

Update Sept. 2018: Überprüfen Sie, ob Docker 18.06 dasselbe Problem hat ( , das nicht auftreten sollte , nach moby/moby, Ausgabe 33794 . ) und auch moby/moby, Ausgabe 35407 und PR 37172 , Teil des 18.06 Versionshinweise ).


2016:

Das Ubuntu Dockerfile beinhaltet:

CMD ["/bin/bash"]

Das bedeutet, dass die Standardeinstellung ENTRYPOINTsh -c Ist (und ich bezweifle, dass tput line In einer sh Sitzung gut funktioniert, da tput verwendet die Datenbank terminfo, die möglicherweise nur für Bash in diesem Bild festgelegt ist.)

Sie können versuchen, ENTRYPOINT mit bash -c Zu überschreiben und zu prüfen, ob dies besser funktioniert.

Das funktioniert jedoch nicht über die Befehlszeile:

docker run --entrypoint /bin/bash --rm  -it ubuntu:16.04 -i -c 'tput lines'
24

Ich werde die Option zum Definieren eines benutzerdefinierten Bildes prüfen.

FROM ubuntu:16.04
ENTRYPOINT ["/bin/bash", "-c"]

Das Ergebnis ist jedoch dasselbe:

docker run --rm  -it u 'tput lines'
24

Dies "funktioniert" jedoch:

FROM ubuntu:16.04
ENTRYPOINT [ "/bin/bash" ]

Mit:

[email protected]:/c/Users/vonc/prog/testsu$ docker run --rm  -it u -i -c 'ls; tput lines'
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
48

Möglicherweise liegt ein Synchronisierungsproblem vor, da derselbe Befehl von Zeit zu Zeit 24 zurückgibt.

Tatsächlich ergibt immer "nicht 24" mit:

FROM ubuntu:16.04
ENTRYPOINT [ "/bin/bash", "-l", "-i", "-c" ]

docker run --rm  -it u -c 'sleep 0.1; ls; tput lines'
48

Das OP-Silgon schlägt in den Kommentaren vor:

docker run --rm -it --entrypoint /bin/bash ubuntu:16.04 -c "sleep 0.1 && tput lines"

Als BMitch Kommentare unten :

In Anbetracht des Erfolgs des Schlafens besteht mein Verdacht darin, dass Docker den Container mit dem Befehl running dreht und der Client nach dem Start eine Verbindung zum laufenden Container herstellt. Normalerweise dauert dies Millisekunden.

Das brachte mich auf eine andere Idee:

[email protected]:/c/Users/vonc/prog/testsu$ 
docker run --entrypoint='/bin/bash' --name ub -d -it ubuntu:16.04
  0d9b8783afbb5e3ff4232da071d3f357985351ea1ce4d142bf6617ac456fb76b
[email protected]:/c/Users/vonc/prog/testsu$ 
d attach ub
  [email protected]:/# tput lines
  48
  [email protected]:/# exit
exit
[email protected]:/c/Users/vonc/prog/testsu$ drmae
0d9b8783afbb5e3ff4232da071d3f357985351ea1ce4d142bf6617ac456fb76b

Ein tput lines Innerhalb einer angehängten Sitzung funktioniert einwandfrei.
(Siehe " So entfernen Sie alte und nicht verwendete Docker-Bilder " im Alias ​​"drmae")


thajeztah fügt in die Kommentare ein :

der Container wird erstellt und dann mit den Standardeinstellungen (80x24) gestartet. Danach (wenn -it) wird eine Sitzung angehängt.
Die Sitzung gibt die Größe des Terminals an.

Siehe API " Ändern der Größe eines Containers TTY ".

 DEBU[0244] Calling POST /v1.25/containers/c42fd5c4eb79c06fd7f9912b8359022f7d93887afbb33b57a67ed8bb7bfee4‌​3a/resize?h=46&w=221 

Weitere Informationen finden Sie unter docker issue 25450 .
Es bezieht sich auf Problem 10341 "Container erstellen oder starten sollte Höhe/Breite-Parameter akzeptieren" . Aleksa Sarai (Zypern) fügt hinzu ( Sept. 2016 ):

Dies ist in der Laufzeitspezifikation ( opencontainers/Laufzeitspezifikation PR 563 ) tatsächlich wieder aufgetaucht.
Da Windows die Möglichkeit erfordert, die Konsolengröße beim ersten Start festzulegen, wird sie möglicherweise für alle Plattformen hinzugefügt .


Das Silgon OP verweist auf den Code in api/client/container/run.go :

// Telling the Windows daemon the initial size of the tty during start makes
// a far better user experience rather than relying on subsequent resizes
// to cause things to catch up.
if runtime.GOOS == "windows" {
    hostConfig.ConsoleSize[0], hostConfig.ConsoleSize[1] = dockerCli.GetTtySize()
}

Mit der logischen Frage:

wäre es sinnvoll, diese Eigenschaft auch unter Linux zu verwenden und die anfängliche Konsolengröße mit diesem Wert festzulegen?

Kenfe-Mickaël Laventure (mlaventure) ist darauf und ein neuer Patch könnte es zu Docker 1.13 schaffen ).

16
VonC

AKTUALISIEREN

sie können jetzt goinside Befehlszeilentool installieren mit:

Sudo npm install -g goinside

und gehen Sie in einen Docker-Container mit der richtigen Terminalgröße mit:

goinside docker_container_name

Logik hinter Goinside

dank @VonC antwort wir haben eine lösung für dieses problem mit einem einfachen bash-schnipsel, das wir in ~/.profile eingefügt haben:

goinside(){
    docker exec -it $1 bash -c "stty cols $COLUMNS rows $LINES && bash";
}
export -f goinside

jetzt können Sie ohne Probleme mit der Terminalgröße in einen Docker-Container gelangen:

$ goinside containername


Denken Sie an source ~/.profile, bevor Sie die goinside-Funktion verwenden.


aktivieren der automatischen Vervollständigung in bash

Wenn Sie die automatische Vervollständigung für goinside aktivieren möchten, können Sie dieses Snippet in .profile verwenden:

goinside(){
    docker exec -it $1 bash -c "stty cols $COLUMNS rows $LINES && bash";
}
_goinside(){
    COMPREPLY=( $(docker ps --format "{{.Names}}" -f name=$2) );
}
complete -F _goinside goinside;
export -f goinside;

aktivieren der automatischen Vervollständigung in zsh

wenn Sie zsh als Standardterminal verwenden, können Sie dieses Snippet in Ihrer ~/.zshrc-Datei verwenden:

autoload bashcompinit
bashcompinit
goinside(){
    docker exec -it $1 bash -c "stty cols $COLUMNS rows $LINES && bash";
}
_goinside(){
    COMPREPLY=( $(docker ps --format "{{.Names}}" -f name=$2) );
}
complete -F _goinside goinside;
export goinside;
42
Soorena

Die Kommentare zu sh versus terminfo sind weitgehend irrelevant. Der relevante Teil (in der gegebenen Antwort nicht klar) ist die Art und Weise, wie der Befehl ausgeführt wird. tput überprüft drei Funktionen in der folgenden Reihenfolge (mit setupterm ):

  1. die Größe des Terminals aus der terminfo-Datenbank (viele Beschreibungen geben diese Information nicht wieder, aber mit TERM=xterm, es ist 24 durch 80 ),
  2. die tatsächliche Anzahl der Zeilen, wenn diese Informationen vom Betriebssystem abgerufen werden können (d. h. die aktuelle Fenstergröße), und
  3. die Umgebungsvariablen LINES und COLUMNS.

Ein Befehl, der ohne interaktive Shell ausgeführt wird könnte so ausgeführt werden, dass die aktuelle Fenstergröße nicht ermittelt wird. Dies ist beispielsweise eine Funktion von ssh (das -t Möglichkeit). Es wäre für Docker auch möglich (obwohl sinnlos), die Variablen LINES und COLUMNS zu setzen.

Jeder Fall (1) oder (3) reicht aus, um das Verhalten zu erklären; Zeitverzögerungen und Rennen einzuführen, tut das nicht.

1
Thomas Dickey
1
Nico Toub

Eine schöne Möglichkeit, bash im Container auszuführen, ohne auf Leitungsprobleme zu stoßen, ist hier :

docker exec -e COLUMNS="`tput cols`" -e LINES="`tput lines`" -ti container bash
0
NotSoShabby

Ich habe gerade mit der Version Docker version 18.06.1-ce, build e68fc7a getestet. Es scheint das gleiche Problem zu haben. Einer der Jungs in der github Ausgabe gab eine praktische Abhilfe :

docker run --rm -it -e COLUMNS=$COLUMNS -e LINES=$LINES -e TERM=$TERM -it ubuntu:16.04 tput lines
0
silgon