web-dev-qa-db-fra.com

Nombre de lignes dans le terminal qui change dans le menu fixe

Je voudrais savoir comment changer le comportement suivant. Disons que mon terminal a 28 lignes. Ensuite, j'utilise les commandes suivantes:

$ 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
root@810effa2777c:/# tput lines
28

Comme vous pouvez le constater, même lorsque tous les résultats doivent être 28, lorsque j’appelle le conteneur au format docker run --rm -it ubuntu:16.04 tput lines, il me donne toujours 24 malgré la taille de mon terminal. Ce n’est pas seulement avec le conteneur ubuntu, j’ai aussi essayé avec debian (docker run --rm -it debian tput lines) et j’ai le même résultat 24.

Le but de ceci est d’utiliser le outil de présentation mdp qui prend en compte les lignes de votre terminal. Lorsque mon implémentation a échoué, j'ai essayé le implémentation de docker d'une autre personne, mais j'ai rencontré la même erreur.

Voici mon erreur dans une image:

Docker number of lines in terminal changing inside docker

Est-ce que quelqu'un a une idée de ce que cela pourrait être et comment cela peut-il être résolu?

32
silgon

Mise à jour septembre 2018: vérifie si le menu fixe 18.06 a le même problème ( il ne devrait pas , après moby/moby numéro 33794 , et aussi moby/moby numéro 35407 et PR 37172 , composant de les notes de publication 18.06 ).


2016:

Le Ubuntu Dockerfile comprend:

CMD ["/bin/bash"]

Cela signifie que la valeur par défaut ENTRYPOINT est sh -c (et je doute que tput line fonctionne bien dans une session sh, car tput utilise la base de données terminfo, qui peut être définie uniquement pour bash dans cette image)

Vous pouvez essayer d'écraser ENTRYPOINT avec bash -c et vérifier si cela fonctionne mieux.

Cela ne fonctionne pas en ligne de commande cependant:

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

Je vérifierai la possibilité de définir une image personnalisée.

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

Le résultat est le même si:

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

Ceci cependant "fonctionne":

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

Avec:

docker@default:/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

Il peut y avoir un problème de synchronisation, car la même commande renvoie 24 de temps en temps.

En fait, les toujours suivants retournent "pas 24" avec:

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

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

Le OP silgon propose dans les commentaires :

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

As BMitch comments ci-dessous :

Étant donné le succès de sleep, je soupçonne que docker lance le conteneur avec la commande en cours d'exécution, puis que le client se connecte au conteneur en cours d'exécution. Généralement, cela prend des millisecondes.

Cela m'a donné une autre idée:

docker@default:/c/Users/vonc/prog/testsu$ 
docker run --entrypoint='/bin/bash' --name ub -d -it ubuntu:16.04
  0d9b8783afbb5e3ff4232da071d3f357985351ea1ce4d142bf6617ac456fb76b
docker@default:/c/Users/vonc/prog/testsu$ 
d attach ub
  root@0d9b8783afbb:/# tput lines
  48
  root@0d9b8783afbb:/# exit
exit
docker@default:/c/Users/vonc/prog/testsu$ drmae
0d9b8783afbb5e3ff4232da071d3f357985351ea1ce4d142bf6617ac456fb76b

Un tput lines dans une session attachée fonctionne parfaitement.
(Sur l'alias drmae, voir " Comment supprimer des images Docker anciennes et inutilisées ")


thajeztah ajoute dans les commentaires :

le conteneur est créé, puis démarré avec les valeurs par défaut (80x24), puis une session est attachée (lorsque -it).
La session spécifie la taille du terminal; 

Voir " Redimensionner un conteneur TTY " API.

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

Pour plus d'informations, voir numéro 25450 de docker .
Il est lié à la question numéro 10341 "La création ou le démarrage du conteneur doit accepter les paramètres hauteur/largeur" ​​ . Aleksa Sarai (cyphar) ajoute (sept. 2016):

Cela a en fait surgi de nouveau dans la spécification d’exécution ( opencontainers/spéc. D’exécution PR 563 ).
Fondamentalement, étant donné que Windows requiert la possibilité de définir la taille de la console au premier démarrage, il est possible que nous finissions par l’ajouter pour toutes les plateformes.


Le OP silgon indique le code dans 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()
}

Avec la question logique:

serait-il judicieux d'utiliser également cette propriété sous Linux et de définir la taille initiale de la console à l'aide de cette valeur?

Kenfe-Mickaël Laventure (mlaventure) est dessus, et un nouveau patch pourrait le rendre à Docker 1.13 .

15
VonC

METTRE À JOUR

vous pouvez maintenant installer l'outil de ligne de commande goinside avec:

Sudo npm install -g goinside

et entrez dans un conteneur de menu fixe avec une taille de terminal appropriée avec:

goinside docker_container_name

La logique derrière le côté

grâce à @VonC answer nous avons une solution à ce problème avec un simple extrait de code que nous avons inséré dans ~/.profile:

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

vous pouvez maintenant entrer dans un conteneur Docker sans problèmes de taille de terminal avec:

$ goinside containername


Remember to source ~/.profile avant d'utiliser la fonction goinside.


permettant l'auto-complétion dans bash

(comme il est partagé dans l'un des commentaires ci-dessous) si vous souhaitez activer l'auto-complétion pour goinside, vous pouvez utiliser cet extrait dans .profile:

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;

permettant l'auto-complétion dans zsh

si vous utilisez zsh comme terminal par défaut, vous pouvez utiliser cet extrait de code dans votre fichier ~/.zshrc:

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

Les commentaires sur sh versus terminfo sont en grande partie hors de propos. La partie pertinente (pas claire dans la réponse donnée) est la façon dont la commande est exécutée. tput vérifie trois fonctions dans l'ordre suivant (à l'aide de setupterm ):

  1. la taille du terminal de la base de données terminfo (de nombreuses descriptions ne donnent pas cette information, mais avec TERM=xterm, il s'agit de 24 sur 80),
  2. le nombre réel de lignes s'il peut obtenir ces informations du système d'exploitation (c'est-à-dire la taille de la fenêtre actuelle), et
  3. les variables d'environnement LINES et COLUMNS.

Une commande exécutée sans Shell interactif pourrait être exécutée de manière à exclure l'obtention de la taille de la fenêtre actuelle. Par exemple, il s’agit d’une caractéristique de ssh (l’option -t). En outre, il serait possible (bien que inutile) pour Docker de définir les variables LINES et COLUMNS.

Les cas (1) ou (3) suffisent à expliquer le comportement; introduire des délais et des courses ne fait pas cela.

1
Thomas Dickey
1
Nico Toub

Une bonne façon de lancer bash dans le conteneur sans rencontrer de problèmes de ligne est ici :

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

Je viens de tester avec la version Docker version 18.06.1-ce, build e68fc7a. Il semble avoir le même problème. Cependant, un des gars du problème github a donné une solution de contournement pratique :

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