这个选项到底有什么作用?我在 TTY 上读了很多书,但我仍然很困惑。我在没有 -t
和只有 -i
的情况下玩耍,似乎期望用户输入的程序在没有 -t
的情况下抛出错误。为什么启用伪 TTY 很重要?
原文由 user1099123 发布,翻译遵循 CC BY-SA 4.0 许可协议
这个选项到底有什么作用?我在 TTY 上读了很多书,但我仍然很困惑。我在没有 -t
和只有 -i
的情况下玩耍,似乎期望用户输入的程序在没有 -t
的情况下抛出错误。为什么启用伪 TTY 很重要?
原文由 user1099123 发布,翻译遵循 CC BY-SA 4.0 许可协议
迟到的答案,但可能会帮助某人
docker run/exec -i
将容器内命令的STDIN连接到 docker run/exec
本身的STDIN。
所以
docker run -i alpine cat
给你一个空行等待输入。输入“你好”,你会得到一个回声“你好”。在您发送 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
连接到终端输入时,此输入未连接到您的输入。您输入的“你好”没有达到 cat
的输入。 cat
正在等待永远不会到达的输入。echo "hello" | docker run -t alpine cat
也会给你一个空行,并且不会在 CTRL
- D
上退出容器,但你不会得到回声“你好”,因为你没有通过 -i
如果你发送 CTRL
+ C
,你会得到你的 shell,但是如果你现在尝试 docker ps
,你会看到 cat
容器仍在运行。这是因为 cat
仍在等待从未关闭的输入流。我没有发现 -t
没有与 -i
结合的任何有用用途。
现在,一起为 -it
。这告诉 cat 它的输入是一个终端,同时将此终端连接到 docker run
的输入,这是一个终端。 docker run/exec
将确保它自己的输入实际上是一个 tty,然后再将其传递给 cat
。这就是为什么你会得到一个 input device is not a TTY
如果你尝试 echo "hello" | docker run -it alpine cat
因为在这种情况下, docker run
的输入本身是来自上一个回声的管道,而不是执行 docker run
的终端
最后,为什么你需要传递 -t
如果 -i
将把你的输入连接到 cat
的输入?这是因为如果输入是终端,命令会以不同的方式处理输入。这也是最好的例子
docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -u root -p
会给你一个密码提示。如果您键入密码,则字符会明显打印出来。docker run -i alpine sh
会给你一个空行。如果您键入 ls
类的命令,您会得到输出,但不会得到提示或彩色输出。在最后两种情况下,您会出现此行为,因为 mysql
以及 shell
没有将输入视为 tty,因此没有使用 tty 特定行为,例如屏蔽输入或着色输出。
原文由 Ahmed Ghonim 发布,翻译遵循 CC BY-SA 4.0 许可协议
2 回答802 阅读✓ 已解决
1 回答680 阅读✓ 已解决
1 回答624 阅读
-t
选项用于 Unix/Linux 如何处理终端访问。过去,终端是硬线连接,后来是基于调制解调器的连接。这些具有物理设备驱动程序(它们是真实的设备)。一旦通用网络开始使用,就开发了一个伪终端驱动程序。这是因为它在了解可以使用哪些终端功能而无需直接将其写入程序(阅读stty
,curses
上的手册页)之间产生了分离。因此,以它为背景,运行一个没有选项的容器,默认情况下你有一个标准输出流(所以
docker run | <cmd>
有效);使用-i
运行,然后添加标准输入流(所以<cmd> | docker run -i
有效);使用-t
,通常在组合中-it
并且您添加了一个终端驱动程序,如果您正在与该进程进行交互,这可能是您想要的。它基本上使容器启动看起来像一个终端连接会话。