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

Mik*_*sin 24 linux tty docker

这是一个有效的命令:

$ echo 'hi there' | docker run -i ubuntu cat
hi there
Run Code Online (Sandbox Code Playgroud)

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

$ echo 'hi there' | docker run -it ubuntu cat
the input device is not a TTY
Run Code Online (Sandbox Code Playgroud)

我想弄清楚这里到底发生了什么。不仅仅是“删除 -t 它将被修复”。

我知道docker run's-t选项代表“分配伪 TTY”,我已经阅读了 TTY 代表什么的历史概述,但这并没有帮助我理解这里违反了什么样的合同。

小智 15

迟到的答案,但可能会帮助某人

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

所以

  • docker run -i alpine cat给你一个等待输入的空行。输入“你好”你会得到一个回声“你好”。在您发送 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”没有到达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. 这就是为什么你会得到 ainput device is not a TTY如果你尝试,echo "hello" | docker run -it alpine cat因为在这种情况下,docker run它本身的输入是来自前一个 echo 的管道,而不是docker run执行的终端

最后,为什么你需要通过-tif-i将你的输入连接到cat's input的技巧?这是因为如果输入是终端,命令会以不同的方式处理输入。这也最好通过例子来说明

  • docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -uroot -p会给你一个密码提示。如果您输入密码,字符会被清晰地打印出来。
  • docker run -i alpine sh会给你一个空行。如果您键入命令,就像ls得到输出一样,但不会得到提示或彩色输出。

在最后两种情况下,您会得到这种行为,因为mysqlshell没有将输入视为 tty,因此没有使用 tty 特定行为,例如屏蔽输入或为输出着色。

  • 您应该注意,为了透明起见,您从[此处]复制了自己的答案(/sf/answers/3797806631/) (3认同)

Mik*_*sin 11

这个答案帮助我回过头来:

  • 默认情况下(既没有-i也没有-t选项)Docker 容器只将其输出发送到 STDOUT,
  • -i选项连接到标准输入,
  • -toption 引入了一个终端接口驱动程序,它在 STDIN/STDOUT 之上工作。并且当一个终端驱动被拉入时,与容器的通信必须符合终端接口协议。管道不是一个字符串。