bash Docker 终端中的 Docker 行数在 docker 内更改
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38786615/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Docker number of lines in terminal changing inside docker
提问by silgon
I would like to know how to change the following behavior. Let's say my terminal has 28lines. Then I use the following commands:
我想知道如何更改以下行为。假设我的终端有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
As you can see, even when all the results should be 28, when I'm calling the container as docker run --rm -it ubuntu:16.04 tput lines
it always gives me 24 despite the size of my terminal. This is not only with the ubuntu container, I also tried with debian (docker run --rm -it debian tput lines
) and I'm having the same result 24.
正如您所看到的,即使所有结果都应该是28,当我调用容器时,docker run --rm -it ubuntu:16.04 tput lines
尽管我的终端有多大,它总是给我 24 。这不仅适用于 ubuntu 容器,我还尝试使用 debian ( docker run --rm -it debian tput lines
) 并且得到了相同的结果 24。
The purpose of this is to use the mdp presentation toolwhich takes into account the lines in your terminal. When my implementation failed, I tried some other person's docker implementationbut I ran to the same error.
这样做的目的是使用mdp 演示工具,该工具考虑了终端中的行。当我的实现失败时,我尝试了其他人的docker 实现,但我遇到了同样的错误。
Here's my error in an image:
这是我在图像中的错误:
Does anyone has any idea what it could be and how can this be solved?
有谁知道它可能是什么以及如何解决?
采纳答案by VonC
Update Sept. 2018: check if docker 18.06 has the same issue (it should not, after moby/moby
issue 33794, and also moby/moby
issue 35407and PR 37172, part of the 18.06 release notes).
更新2018年9月:检查是否泊坞窗18.06有同样的问题(它不应该,以后moby/moby
发行33794,以及moby/moby
发行35407和PR 37172,该部分18.06发行说明)。
2016:
2016年:
The Ubuntu Dockerfileincludes:
CMD ["/bin/bash"]
That means the default ENTRYPOINT
is sh -c
(and I doubt tput line
works well in a sh
session, since tputuses terminfo
database, which might be set only for bash in that image)
这意味着默认ENTRYPOINT
是sh -c
(我怀疑tput line
在sh
会话中效果很好,因为tput使用terminfo
数据库,该数据库可能仅针对该图像中的 bash 设置)
You could try overwrite ENTRYPOINT
with bash -c
and check if that works better.
你可以尝试覆盖ENTRYPOINT
与bash -c
和检查,如果是工作得更好。
That does not work from command line though:
但是,这在命令行中不起作用:
docker run --entrypoint /bin/bash --rm -it ubuntu:16.04 -i -c 'tput lines'
24
I will check the option of defining a custom image.
我将检查定义自定义图像的选项。
FROM ubuntu:16.04
ENTRYPOINT ["/bin/bash", "-c"]
The result is the same though:
结果是一样的:
docker run --rm -it u 'tput lines'
24
This however "works":
然而,这“有效”:
FROM ubuntu:16.04
ENTRYPOINT [ "/bin/bash" ]
With:
和:
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
There might be a synchronization issue, as the same command does return 24 from time to time.
可能存在同步问题,因为同一命令会不时返回 24。
Actually, the following alwaysreturn "not 24" with:
实际上,以下总是返回“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
The OP silgonproposes in the comments:
docker run --rm -it --entrypoint /bin/bash ubuntu:16.04 -c "sleep 0.1 && tput lines"
Given the success of sleep my suspicion is that docker spins up the container with the running command, and once up, the client attaches to the running container. Typically something that takes milliseconds.
鉴于 sleep 的成功,我怀疑 docker 使用 running 命令启动容器,一旦启动,客户端就会连接到正在运行的容器。通常需要几毫秒的时间。
That gave me another idea:
这给了我另一个想法:
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
A tput lines
within an attached session works just fine.
(On the drmae
alias, see "How to remove old and unused Docker images")
tput lines
附加会话中的A工作正常。
(关于drmae
别名,请参阅“如何删除旧的和未使用的 Docker 镜像”)
thajeztahadds in the comments:
the container is created, then started with the defaults (
80x24
), and after that (when-it
), a session is attached.
The session is specifying the size of the terminal;
创建容器,然后以默认值 (
80x24
)启动,然后(when-it
) 附加会话。
会话指定终端的大小;
See "Resize a container TTY" API.
请参阅“调整容器 TTY 大小”API。
DEBU[0244] Calling POST /v1.25/containers/c42fd5c4eb79c06fd7f9912b8359022f7d93887afbb33b57a67ed8bb7bfee4??3a/resize?h=46&w=221
For more, see docker issue 25450.
It is related to issue 10341 "Container create or start should accept height/width params". Aleksa Sarai (cyphar)adds (Sept. 2016):
有关更多信息,请参阅docker 问题 25450。
它与问题 10341 “Container create or start should accept height/width params”有关。Aleksa Sarai (cyphar)补充道(2016 年 9 月):
This has actually popped up again inside the runtime-spec (opencontainers/runtime-spec PR 563).
Basically, since Windows requires the ability to set the console size on first start, we might end up adding it for all platforms.
这实际上在运行时规范中再次出现(opencontainers/runtime-spec PR 563)。
基本上,由于 Windows 需要在第一次启动时设置控制台大小的能力,我们最终可能会为所有平台添加它。
The OP silgonpoints out to the code in api/client/container/run.go
:
该OP silgon指出在代码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()
}
With the logical question:
带着逻辑问题:
would it make sense to use this property on Linux as well, and set the initial console size using that value?
在 Linux 上也使用此属性并使用该值设置初始控制台大小是否有意义?
Kenfe-Micka?l Laventure (mlaventure
)is on it, and a new patch could make it to Docker 1.13.
Kenfe-Micka?l Laventure ( mlaventure
)就在它上面,一个新的补丁可以使它进入Docker 1.13。
回答by Soorena
UPDATE
更新
you can now install goinside
command line tool with:
您现在可以goinside
使用以下命令安装命令行工具:
sudo npm install -g goinside
and go inside a docker container with a proper terminal size with:
并进入具有适当终端大小的 docker 容器,其中:
goinside docker_container_name
Logic behind goinside
goinside背后的逻辑
thanks to @VonC answerwe've got a solution for this problem with a simple bash snippet that we put in ~/.profile
:
感谢@VonC 的回答,我们通过一个简单的 bash 代码片段解决了这个问题~/.profile
:
goinside(){
docker exec -it bash -c "stty cols $COLUMNS rows $LINES && bash";
}
export -f goinside
now you are able to get inside a docker container without terminal size issues with:
现在您可以进入 docker 容器,而不会出现终端大小问题:
$ goinside containername
$ goinside containername
rememberto source ~/.profile
before using the goinside
function.
记得到source ~/.profile
使用前goinside
的功能。
enabling autocompletion in bash
在 bash 中启用自动完成
(as it's shared in one of comments below) if you want to enable autocompletion for goinside
you can use this snippet in .profile
:
(因为它在下面的评论之一中共享)如果您想启用自动完成功能,goinside
您可以在以下代码段中使用.profile
:
goinside(){
docker exec -it bash -c "stty cols $COLUMNS rows $LINES && bash";
}
_goinside(){
COMPREPLY=( $(docker ps --format "{{.Names}}" -f name=) );
}
complete -F _goinside goinside;
export -f goinside;
enabling autocompletion in zsh
在 zsh 中启用自动完成
if you are using zsh
as your default terminal you can use this snippet inside your ~/.zshrc
file:
如果您使用的zsh
是默认终端,则可以在~/.zshrc
文件中使用此代码段:
autoload bashcompinit
bashcompinit
goinside(){
docker exec -it bash -c "stty cols $COLUMNS rows $LINES && bash";
}
_goinside(){
COMPREPLY=( $(docker ps --format "{{.Names}}" -f name=) );
}
complete -F _goinside goinside;
export goinside;
回答by NotSoShabby
回答by Thomas Dickey
The comments about sh
versus terminfo are largely irrelevant. The relevant part (not clear in the given answer) is the way the command is executed. tput
checks three features in the following order (using setupterm
):
关于sh
vs terminfo的评论在很大程度上是无关紧要的。相关部分(在给定的答案中不清楚)是命令的执行方式。 tput
按以下顺序检查三个功能(使用setupterm
):
- the size of the terminal from the terminfo database (many descriptions do not give this information, but with
TERM=xterm
, it is 24by 80), - the actual number of lines if it can get that information from the operating system (i.e., the current window size), and
- the
LINES
andCOLUMNS
environment variables.
- terminfo 数据库中的终端大小(许多描述没有提供此信息,但是使用
TERM=xterm
,它是24x 80), - 如果可以从操作系统获取该信息(即当前窗口大小),则为实际行数,以及
- 在
LINES
和COLUMNS
环境变量。
A command which is run without an interactive shell couldbe executed in a way that precludes getting the current window size. For example, that is a feature of ssh
(the -t
option). Also, it would be possible (though pointless) for Docker to set the LINES
and COLUMNS
variables.
在没有交互式 shell 的情况下运行的命令可以以一种排除获取当前窗口大小的方式执行。例如,这是ssh
(-t
选项)的一个特征。此外,Docker 可以(尽管毫无意义)设置LINES
和COLUMNS
变量。
Either case (1) or (3) is enough to explain the behavior; introducing time-delays and races does not do that.
情况 (1) 或 (3) 都足以解释该行为;引入时间延迟和比赛并不能做到这一点。
回答by Nico Toub
It has been fixed in docker 18.06: https://github.com/moby/moby/issues/33794#issuecomment-406814439
它已在 docker 18.06 中修复:https: //github.com/moby/moby/issues/33794#issuecomment-406814439
回答by silgon
I just tested with version Docker version 18.06.1-ce, build e68fc7a
. It seems to have the same problem. However, one of the guys in the github issuegave a practical workaround:
我刚刚用 version 进行了测试Docker version 18.06.1-ce, build e68fc7a
。它似乎有同样的问题。但是,github 问题中的一个人给出了一个实用的解决方法:
docker run --rm -it -e COLUMNS=$COLUMNS -e LINES=$LINES -e TERM=$TERM -it ubuntu:16.04 tput lines