“输入设备不是TTY”在“ docker run”输出中到底是什么意思?


18

这是一个有效的命令:

$ echo 'hi there' | docker run -i ubuntu cat
hi there

这是一条响应并显示错误消息的命令:

$ echo 'hi there' | docker run -it ubuntu cat
the input device is not a TTY

我想弄清楚这里到底发生了什么。不只是“删除-t,它将得到解决”。

我知道docker run-t选项代表‘分配伪TTY’,和我读的是什么TTY代表历史观点,但它并没有帮助我了解什么样的合同在这里侵犯。


这不是多余的,docker可以创建TTY,而无需附加任何内容。您的输出将包含用于颜色等的字符,但是您的终端输出将不会通过管道传递到容器的输入中。因此,在docker命令退出后,您键入的字符将排队等待您运行的下一个命令。
BMitch

我可以在docker中启动tty吗?我有一些停止运行的应用程序,我没有使用来运行docker -t,但是我无法在生产中修改docker start命令。因此,我需要使该应用程序认为它始于-t
mvorisek

Answers:


9

这个答案帮助我重新思考:

  • 默认情况下(既-i没有-t选项,也没有选项),Docker容器仅将其输出发送到STDOUT,
  • -i选件一起连接到STDIN,
  • -toption拉入一个终端接口驱动程序,该驱动程序在STDIN / STDOUT之上运行。并且当引入终端驱动程序时,与容器的通信必须符合终端接口协议。管道不这样做。

7

答案较晚,但可能对某人有帮助

docker run/exec -i会将容器内命令的STDIN连接到容器docker run/exec本身的STDIN 。

所以

  • docker run -i alpine cat给您空行等待输入。输入“ hello”,您将得到回声“ hello”。在发送CTRL + D之前,容器不会退出,因为主进程cat正在等待来自无限流(即的终端输入)的输入docker run
  • 另一方面,echo "hello" | docker -i run alpine cat将显示“ hello”并立即退出,因为会cat注意到输入流已结束并自行终止。

如果您docker ps在退出以上任一方法后尝试,则将找不到任何正在运行的容器。在这两种情况下,cat其自身都已终止,因此docker已终止了该容器。

现在,对于“ -t”,它告诉docker内部的主要过程其输入是终端设备。

所以

  • docker run -t alpine cat会给您空行,但是如果您尝试键入“ hello”,则不会得到任何回显。这是因为当cat连接到端子输入时,此输入未连接到您的输入。您输入的“ hello”未达到的输入catcat正在等待永远不会到达的输入。
  • 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特有的行为,例如掩盖输入或为输出着色。


4

tty表示您有一个终端,这将由xterm或许多linux命令行界面之一提供。它需要与之关联的键盘和文本输出接口。希望这样做的典型原因是对彩色文本输出的支持,各种键组合(如箭头键)的处理以及在屏幕上移动光标的能力。

当如echo示例所示将命令通过管道传递到docker时,该管道是输入,并且该管道没有tty接口,它只是文本流。尝试创建带有tty的tty将失败,如错误消息所示。



对于我来说,“键盘和输出接口”与“ STDIN / STDOUT”之间仍然存在差距。显然,您不能将“光标位置”概念应用于STDOUT,因为STDOUT是流而不是屏幕。什么规范描述了(我猜是)STDOUT之上的输出接口抽象?
米哈伊尔·瓦辛

1
它是在stdin / stdout之上运行的接口。en.wikipedia.org/wiki/POSIX_terminal_interface
BMitch
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.