这个选项到底有什么作用?我读了很多关于TTY的文章,但我还是很困惑。我没有使用-t,只使用-i,看起来程序需要用户输入而不使用-t就会抛出错误。为什么启用伪tty很重要?
当前回答
我对-t的了解如下:
docker exec -ti CONTAINER bash允许我在容器中“登录”。感觉像嘘嘘(其实不是)。
但问题是当我想恢复数据库时。
通常我dodocker exec -ti mysql.5.7 mysql -这里我在容器中执行mysql命令并获得一个交互式终端。
我添加了<dump。sql到前面的命令,以便我可以恢复一个db。但是它失败了,不能在非tty输入上启用tty模式。
删除-t会有所帮助。还是不明白为什么:
docker exec -i mysql.5.7 mysql < dump.sql
最后一个可行。希望这能帮助到人们。
其他回答
-t选项表示Unix/Linux如何处理终端访问。在过去,终端是硬线连接,后来是基于调制解调器的连接。它们具有物理设备驱动程序(它们是真正的设备部件)。一旦广义网络投入使用,伪终端驱动程序就被开发出来。这是因为它在理解哪些终端功能可以使用而不需要直接将其写入程序之间产生了分离(阅读stty, curses的手册页)。
因此,以它为背景,运行一个没有选项的容器,默认情况下,你有一个标准输出流(因此docker运行| <cmd>工作);使用-i运行,你会添加stdin流(所以<cmd> | docker Run -i works);使用-t,通常在-it和您添加的终端驱动程序的组合中使用-t,如果您正在与进程交互,这可能是您想要的。它基本上使容器开始看起来像一个终端连接会话。
每个进程都有三个数据流,即STDIN/ STDOUT/ STDERR。当一个进程在容器中运行时,默认情况下终端与该进程的STDOUT流连接。因此,当在终端中运行docker run命令时,所有的输出流都是可见的。但是如果你想为容器中正在运行的进程提供输入,那么你必须连接进程的STDIN通道,这不是默认情况,而是通过docker run -i命令完成的。
-t用于交互式/格式化的输入操作。
这里的大多数答案都是很好的概念性答案,但我发现他们遗漏了太多细节,让我坐在电脑前无法使用这些信息。Ahmed Gnomin的答案正在逐步成为程序化的,但让我们试着进一步推动它。
首先讲一点理论
TTY Demystified中的两幅图是关键:
我不能声称完全理解了这幅图,但这里的关系是当xterm(或ubuntu中的gnome-terminal;由上图中的一个“user process”气泡表示)打开,它启动一个bash(或任何默认shell),然后通过内核伪终端(PTY)主和从向它发送键盘输入:
Xterm -> PTMX (pty主)-> PTS (pty从)-> bash
第二张图表示在这个简短的bash会话中涉及的进程:
>>> cat
>>> ls | sort
...
关键信息是TTY和stdin、stdout、stderr行。这表明每个进程都与TTY(电传终端)相关联,并且它们的3个流(stdin, stdout, stderr)非常自然地与这个TTY相关联,除了管道或重定向的情况(注意管道ls | sort将ls的stdout与sort的stdin相关联)。
现在来测试一下这个理论
我们可以通过输入tty找到bash使用的伪终端:
>>> tty
/dev/pts/2
Bash因此与PTY从机2相关联(这可能意味着有另一个打开的终端,与主/从机对1相关联)。我们还可以获得Bash的stdin, stdout和stderr流:
>>> 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
实际上,它们都与bash的自然TTY slave相关。$$是一个bash变量,它返回bash的PID。我们同样可以通过使用ps和手动输入来找到它)。
最后用这个理论来回答最初的Docker问题
我们复制了上面的步骤,但这次是在docker容器中:
>>> docker run --rm -t ubuntu tty
/dev/pts/0
>>> docker run --rm ubuntu tty
not a tty
这是有意义的,因为-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
我还是不明白-我到底做了什么…我想要一些帮助! 我能找到的唯一一个有趣的命令,它似乎有区别:
>>> 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]
Docker文档提到-a“附加到作为输入传递的流上”,但我还没有找到解释这意味着什么,以及它与-i选项有什么关系。
-it指示Docker分配一个伪tty连接到容器的stdin,在容器中创建一个交互式bash shell。
——interactive, -i false保持STDIN打开,即使没有附加
——tty, -t false分配一个伪tty
https://docs.docker.com/engine/reference/commandline/run/
我对-t的了解如下:
docker exec -ti CONTAINER bash允许我在容器中“登录”。感觉像嘘嘘(其实不是)。
但问题是当我想恢复数据库时。
通常我dodocker exec -ti mysql.5.7 mysql -这里我在容器中执行mysql命令并获得一个交互式终端。
我添加了<dump。sql到前面的命令,以便我可以恢复一个db。但是它失败了,不能在非tty输入上启用tty模式。
删除-t会有所帮助。还是不明白为什么:
docker exec -i mysql.5.7 mysql < dump.sql
最后一个可行。希望这能帮助到人们。
推荐文章
- 如何在docker映像的新容器中运行bash ?
- docker -撰写持久数据MySQL
- 从主机连接到docker容器中的mysql
- 当我使用Alpine作为基本图像时,如何添加用户?
- Docker -绑定0.0.0.0:4000失败:端口已经分配
- 将Python诗歌与Docker集成
- 如何在系统启动时运行docker-compose up -d ?
- 如何确定一个进程是否运行在lxc/Docker内部?
- 在docker容器上挂载多个卷?
- Kubernetes如何使部署更新映像
- Docker-compose up vs Docker-compose up -build vs Docker-compose build -no-cache
- 在Docker Alpine容器中启动一个shell
- 允许docker容器连接到本地/主机postgres数据库
- 在Docker Desktop中定位数据卷(Windows)
- 如何通过docker运行传递参数到Shell脚本