停靠码头内码头的码头数量

时间:2016-08-05 10:07:23

标签: bash docker terminal tput

我想知道如何更改以下行为。我们说我的终端有 28 行。然后我使用以下命令:

$ 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

正如您所看到的,即使所有结果都应该 28 ,当我将容器称为docker run --rm -it ubuntu:16.04 tput lines时,尽管我的终端尺寸很大,但总是给我24 。这不仅适用于ubuntu容器,我还尝试使用debian(docker run --rm -it debian tput lines)并且我的结果相同24。

这样做的目的是使用考虑终端中线路的mdp presentation tool。当我的实施失败时,我尝试了其他人docker implementation,但我遇到了同样的错误。

这是我在图片中的错误:

Docker number of lines in terminal changing inside docker

有没有人知道它可能是什么以及如何解决这个问题?

6 个答案:

答案 0 :(得分:43)

更新

您现在可以使用以下命令安装goinside命令行工具

sudo npm install -g goinside

然后进入具有正确终端大小的docker容器:

goinside docker_container_name

goinside背后的逻辑

感谢@VonC answer我们通过我们放入~/.profile的简单bash片段找到了解决此问题的方法:

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

现在你可以进入一个没有终端尺寸问题的docker容器:

$ goinside containername

在使用source ~/.profile函数之前,

记住goinside

在bash中启用自动完成功能

(因为它在下面的评论中共享)如果您要为goinside启用自动完成功能,您可以在.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;

在zsh

中启用自动完成功能

如果您使用zsh作为默认终端,则可以在~/.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;

答案 1 :(得分:16)

2018年9月更新:检查docker 18.06是否有同样的问题(it should notmoby/moby issue 33794之后,以及moby/moby issue 35407PR 37172是{{3}的一部分}})。

2016:

18.06 release notes包括:

CMD ["/bin/bash"]

这意味着默认ENTRYPOINTsh -c(我怀疑tput linesh会话中运作良好,因为Ubuntu Dockerfile使用terminfo数据库,可能只为该图像中的bash设置)

您可以尝试使用ENTRYPOINT覆盖bash -c并检查其是否更有效。

但是从命令行开始不起作用:

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

我将检查定义自定义图像的选项。

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

结果是相同的:

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

但这“有效”:

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

使用:

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

可能存在同步问题,因为同一命令会不时返回24。

实际上,以下始终使用以下内容返回“not 24”:

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

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

tput建议OP silgon

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

正如in the comments评论BMitch

  

鉴于睡眠成功,我怀疑docker使用running命令旋转容器,一旦启动,客户端就会连接到正在运行的容器。   通常需要几毫秒的时间。

这给了我另一个想法:

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

附加会话中的tput lines工作正常 (在drmae别名上,请参阅“below”)

How to remove old and unused Docker images添加thajeztah

  

创建容器,然后使用默认值(80x24)启动,之后(-it时),附加会话。
  会话指定终端的大小;

请参阅“in the comments”API。

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

有关详情,请参阅Resize a container TTY 它与docker issue 25450有关。 issue 10341 "Container create or start should accept height/width params"添加了( 2016年9月):

  

这实际上已经在runtime-spec(Aleksa Sarai (cyphar))中再次出现   基本上,由于Windows需要能够在首次启动时设置控制台大小,我们最终可能会为所有平台添加

opencontainers/runtime-spec PR 563指出OP silgon中的代码:

// 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()
}

逻辑问题:

  

在Linux上使用此属性是否有意义,并使用该值设置初始控制台大小?

api/client/container/run.go就在它上面,一个新的补丁可以转到Kenfe-Mickaël Laventure (mlaventure)

答案 2 :(得分:2)

here:在容器内运行bash而不遇到线路问题的一种好方法:

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

答案 3 :(得分:1)

关于sh与terminfo的评论在很大程度上是无关紧要的。相关部分(在给定答案中不清楚)是命令执行的方式。 tput按以下顺序检查三个功能(使用setupterm):

  1. 来自terminfo数据库的终端大小(许多描述不提供此信息,但TERM=xterm 24 80 ),
  2. 如果可以从操作系统获取该信息的实际行数(即当前窗口大小),
  3. LINESCOLUMNS环境变量。
  4. 在没有交互式shell 的情况下运行的命令可以以阻止获取当前窗口大小的方式执行。例如,这是ssh-t选项)的一项功能。此外,Docker可能(尽管毫无意义)设置LINESCOLUMNS变量。

    情况(1)或(3)足以解释行为;引入时间延迟和比赛不会那样做。

答案 4 :(得分:1)

答案 5 :(得分:1)

我刚刚测试了版本Docker version 18.06.1-ce, build e68fc7a。似乎有同样的问题。但是,github issue中的一个人给了practical workaround

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