这个选项到底是做什么的?我一直在读TTY,但我仍然感到困惑.我玩的没有-t
和只是-i
,似乎期望用户输入的程序抛出错误没有-t
.为什么启用伪TTY很重要?
小智 167
"-t"选项指向Unix/Linux如何处理终端访问.在过去,终端是强硬连接,后来是基于调制解调器的连接.这些都有物理设备驱动程序(它们是真正的设备).一旦广义网络投入使用,就开发了伪终端驱动程序.这是因为它在理解可以使用哪些终端功能而无需直接将其写入程序之间创建了分离(阅读手册页-t
,stty
).
所以,以它为背景,运行一个没有选项的容器,默认情况下你有一个stdout流(所以curses
工作); 用"-i"运行,你得到stdin流添加(所以docker run | <cmd>
工作); 使用"-t",通常在组合"-it"中添加一个终端驱动程序,如果你正在与流程进行交互,那么你可能会想要它.它基本上使容器启动看起来像终端连接会话.
小智 70
根据Google搜索,"-t"参数没有很好地记录,或者很多人经常提到.
当您通过在Bash提示符下键入"docker"(使用最新版本的1.8.1)显示所有docker客户端参数的列表时,它甚至不会显示.
事实上,如果您尝试通过键入"docker -t --help"获得有关此参数的特定帮助,如果给出了这个非常模糊的回复:
"提供了标志但未定义:-t"
所以,你不能因为对这个论点感到困惑而受到指责!
在Docker在线文档中提到它是"分配伪tty"并且经常与-i一起使用:
https://docs.docker.com/reference/run/
我通过以下方式看到它在极好的jwilder/nginx-proxy docker容器的文档中使用:
docker run -d -p 80:80 --name nginx -v /tmp/nginx:/etc/nginx/conf.d -t nginx
Run Code Online (Sandbox Code Playgroud)
在这种情况下,它所做的是将输出发送到此docker容器中的'virtual'tty(Bash命令提示符/终端).然后,您可以通过运行docker命令"docker logs CONTAINER"来查看此输出,其中CONTAINER是此容器ID的前几个字符.输入"docker ps -a"即可找到此CONTAINER ID
我在下面的链接中看到过这个"-t"参数,它说:"-t和-i标志分配一个伪tty并保持stdin打开,即使没有附加.这将允许你使用只要bash提示符正在运行,就像传统的VM一样容器."
https://coreos.com/os/docs/latest/getting-started-with-docker.html
我希望这有帮助!我不确定为什么没有记录或使用太多.也许它是实验性的,并将在即将推出的版本中作为文档功能实现.
Ahm*_*nim 53
答案较晚,但可能对某人有帮助
docker run/exec -i
会将容器内命令的STDIN连接到容器docker run/exec
本身的STDIN 。
所以
docker run -i alpine cat
给您空行等待输入。输入“ hello”,您将得到回声“ hello”。除非您发送CTRL+,否则容器不会退出,D因为主进程cat
正在等待来自无限流(即的终端输入)的输入docker run
。echo "hello" | docker run -i alpine cat
将显示“ hello”并立即退出,因为会cat
注意到输入流已结束并自行终止。如果您docker ps
在退出以上任何一个方法后尝试,则将找不到任何正在运行的容器。在这两种情况下,cat
它本身都已终止,因此docker已终止了该容器。
现在,对于“ -t”,它告诉docker内部的主要过程其输入是终端设备。
所以
docker run -t alpine cat
将给您空行,但是如果您尝试键入“ hello”,则不会得到任何回显。这是因为当cat
连接到端子输入时,此输入未连接到您的输入。您输入的“ hello”未达到的输入cat
。cat
正在等待永远不会到达的输入。echo "hello" | docker run -t alpine cat
也会给您空行,并且不会退出容器CTRL- D但是您不会收到回声“ hello”,因为您没有通过-i
如果发送CTRL+ C,则返回外壳,但是如果现在尝试docker ps
,则看到cat
容器仍在运行。这是因为cat
仍在等待从未关闭的输入流。如果不-t
与结合使用,我还没有发现任何有用的用途-i
。
现在,为了-it
在一起。这告诉cat它的输入是端子,同时将此端子连接到其输入docker run
是端子。docker run/exec
在将自己的输入传递给之前,将确保它的输入实际上是tty cat
。这就是为什么input device is not a TTY
尝试时会得到a的echo "hello" | docker run -it alpine cat
原因,因为在这种情况下,其docker run
自身的输入是来自先前回显的管道,而不是docker run
执行终端
最后,-t
如果-i
要执行将输入连接到输入的技巧,您为什么需要通过cat
?这是因为如果命令是终端,则命令对输入的处理会有所不同。这也是最好的例子
docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -uroot -p
会提示您输入密码。如果您输入密码,则字符将被清晰地打印出来。docker run -i alpine sh
给你一个空行。如果键入类似的命令,ls
则会得到输出,但不会得到提示或彩色输出。在后两种情况下,您之所以会得到这种行为,是因为mysql
他们并shell
没有将输入视为tty,因此没有使用tty特有的行为,例如掩盖输入或为输出着色。
sam*_*laf 21
Most of the answers here are great conceptual answers, but I found that they left out too many details for me to be able to use the information while sitting at the computer. Ahmed Gnomin's answer is on its way to being programmatic, but let's try to push it one step further.
Two images in The TTY Demystified are key:
I can't claim to fully understand this picture, but the relationship of interest here is that when xterm (or gnome-terminal in ubuntu; represented by one of the "user process" bubbles in the above image) opens up, it starts a bash (or whichever default shell), and then sends keyboard inputs to it via the kernel pseudo-terminal (PTY) master and slave:
xterm -> ptmx (pty master) -> pts (pty slave) -> bash
The second image represents the processes' involved in this short bash session:
>>> cat
>>> ls | sort
...
Run Code Online (Sandbox Code Playgroud)
The key bits of information are the TTY and stdin, stdout, stderr lines. This shows that each process is associated to a TTY (teletype terminal), and that their 3 streams (stdin, stdout, stderr) are quite naturally associated to this TTY, except in the case of pipes or redirections (notice that the pipe ls | sort
associates ls' stdout to sort's stdin).
We can find the pseudo-terminal used by bash by typing tty
:
>>> tty
/dev/pts/2
Run Code Online (Sandbox Code Playgroud)
Bash is thus associated to the PTY slave number 2 (this probably means that there is another terminal open, associated to the master/slave pair 1). We can also get bash's stdin, stdout, and stderr streams:
>>> ls -l /proc/$$/fd
lrwx------ 1 samlaf samlaf 64 Jun 17 21:50 0 -> /dev/pts/2
lrwx------ 1 samlaf samlaf 64 Jun 17 21:50 1 -> /dev/pts/2
lrwx------ 1 samlaf samlaf 64 Jun 17 21:50 2 -> /dev/pts/2
Run Code Online (Sandbox Code Playgroud)
事实上,它们都与 bash 的天然 TTY 从属相关。($$
是一个 bash 变量,它返回 bash 的 PID。我们同样可以通过使用ps
并手动输入它来找到它)。
我们重现上述步骤,但这次是在 docker 容器内:
>>> docker run --rm -t ubuntu tty
/dev/pts/0
>>> docker run --rm ubuntu tty
not a tty
Run Code Online (Sandbox Code Playgroud)
这是有道理的,因为-t
分配了一个伪终端。
相关命令-i
更难解释。
>>> docker run --rm ubuntu bash -c "ls -l /proc/\$\$/fd"
lrwx------ 1 root root 64 Jun 18 02:37 0 -> /dev/null
l-wx------ 1 root root 64 Jun 18 02:37 1 -> pipe:[9173789]
l-wx------ 1 root root 64 Jun 18 02:37 2 -> pipe:[9173790]
>>> docker run --rm -t ubuntu bash -c "ls -l /proc/\$\$/fd"
lrwx------ 1 root root 64 Jun 18 02:39 0 -> /dev/pts/0
lrwx------ 1 root root 64 Jun 18 02:39 1 -> /dev/pts/0
lrwx------ 1 root root 64 Jun 18 02:39 2 -> /dev/pts/0
>>> docker run --rm -it ubuntu bash -c "ls -l /proc/\$\$/fd"
lrwx------ 1 root root 64 Jun 18 02:39 0 -> /dev/pts/0
lrwx------ 1 root root 64 Jun 18 02:39 1 -> /dev/pts/0
lrwx------ 1 root root 64 Jun 18 02:39 2 -> /dev/pts/0
Run Code Online (Sandbox Code Playgroud)
我仍然不明白到底-i
是什么......我希望得到一些帮助!我能找到的唯一有趣的命令似乎是有区别的:
>>> docker run --rm -a stdout -i ubuntu bash -c "ls -l /proc/\$\$/fd"
lr-x------ 1 root root 64 Jun 18 02:43 0 -> pipe:[9199896]
l-wx------ 1 root root 64 Jun 18 02:43 1 -> pipe:[9199897]
l-wx------ 1 root root 64 Jun 18 02:43 2 -> pipe:[9199898]
>>> docker run --rm -a stdout ubuntu bash -c "ls -l /proc/\$\$/fd"
lrwx------ 1 root root 64 Jun 18 02:43 0 -> /dev/null
l-wx------ 1 root root 64 Jun 18 02:43 1 -> pipe:[9197938]
l-wx------ 1 root root 64 Jun 18 02:43 2 -> pipe:[9197939]
Run Code Online (Sandbox Code Playgroud)
Docker文档提到 -a “附加到作为输入传递的流”,但我无法找到这意味着什么以及它与选项有何关系的解释-i
。
gat*_*sec 17
组合选项-it
称为交互模式。
默认情况下,容器只有一个标准输出流(即docker run | CMD
工作流),为了与我们的容器交互,我们需要这两个选项:
-i
添加一个标准输入流(即CMD | docker run
有效);-t
分配一个伪 TTY 主/从对,从属部分与容器中正在运行的进程相关联,主部分与 docker 命令相关联。标准输入流将容器附加到 shell 的标准输入(docker 继承 shell 的标准输入流),而 TTY 线路规则使您能够以键盘方式与容器交互。
TTY 线路规程由内核向 TTY 设备提供的低级功能组成,例如编辑缓冲区和基本线路编辑命令。
如下所示,您可以使用以下命令检查标准文件描述符:
docker run --rm -i ubuntu sh -c "ls -l /proc/\$\$/fd"
Run Code Online (Sandbox Code Playgroud)
如果删除,-i
您将看到 stdin 指向/dev/null
(即,没有分配流)。
我所知道的-t
是以下内容:
docker exec -ti CONTAINER bash
- 允许我在容器中"登录".感觉像sshing(不是).
但问题是我想要恢复数据库.
通常我这样做docker exec -ti mysql.5.7 mysql
- 在这里我在容器中执行mysql命令并获得一个交互式终端.
我添加<dump.sql
到上一个命令,所以我可以恢复数据库.但它失败了cannot enable tty mode on non tty input
.
删除-t
帮助.还是不明白为什么:
docker exec -i mysql.5.7 mysql < dump.sql
Run Code Online (Sandbox Code Playgroud)
最后一个有效.希望这有助于人们.
归档时间: |
|
查看次数: |
43623 次 |
最近记录: |