错误“输入设备不是 TTY”
Posted
技术标签:
【中文标题】错误“输入设备不是 TTY”【英文标题】:Error "The input device is not a TTY" 【发布时间】:2017-08-23 06:31:39 【问题描述】:我正在从我的Jenkinsfile
运行以下命令。但是,我收到错误“输入设备不是 TTY”。
docker run -v $PWD:/foobar -it cloudfoundry/cflinuxfs2 /foobar/script.sh
有没有办法在不使用交互模式的情况下从Jenkinsfile
运行脚本?
我基本上有一个名为 script.sh
的文件,我想在 Docker 容器中运行它。
【问题讨论】:
对于*nix,这里好像没有解决办法。 'docker exec -i' 不起作用,'-t' 也不起作用。 @rjurney 你有没有找到 docker exec 的解决方案?我试过 -i 和 -t 没有成功。 docker exec -it mycontainer bash certbot --apache -d www.website.com --email *********@gmail.com --agree-tos -n 【参考方案1】:从您的 cli 中删除 -it
以使其非交互并删除 TTY。如果您也不需要,例如在 Jenkins 或 cron 脚本中运行你的命令,你应该这样做。
或者,如果您通过管道输入不是来自 TTY 的 docker 命令,则可以将其更改为 -i
。如果您的命令行中有 xyz | docker ...
或 docker ... <input
之类的内容,请执行此操作。
如果您想要 TTY 支持但输入设备上没有它,您可以将其更改为 -t
。为检查 TTY 以启用日志中输出颜色格式的应用程序执行此操作,或者当您稍后使用适当的终端附加到容器时执行此操作。
或者,如果您需要一个交互式终端并且不在 Linux 或 MacOS 上的终端中运行,请使用不同的命令行界面。据报道 PowerShell 在 Windows 上包含此支持。
什么是 TTY?它是一个终端界面,支持转义序列、移动光标等,来自连接到大型机的愚蠢终端的旧时代。今天它由 Linux 命令终端和 ssh 接口提供。请参阅wikipedia article for more details。
要查看使用和不使用 TTY 运行容器的区别,请在没有 TTY 的情况下运行容器:docker run --rm -i ubuntu bash
。在该容器内,使用apt-get update; apt-get install vim
安装vim。请注意缺少提示。对文件运行 vim 时,尝试在文件中移动光标。
【讨论】:
我将此命令与mysql -p
结合使用,但未指定密码。当只添加-i
时,密码提示永远不会出现。只需添加-t
就会出现提示,但它似乎根本没有读取输入(按字面意思打印而不是被提示隐藏),即使在点击返回时也是如此;只有 ctrl-c 可以结束它。以某种方式可以将mysql客户端与docker一起使用吗?
谢谢你!对于 docker-compose 用户,我想补充一点,我有一个类似的命令要运行 - 我想根据模式删除 redis 键 - 并且能够使用 docker-compose exec -T
命令执行此操作。来自docker-compose exec
的手册页:Disable pseudo-tty allocation. By default docker-compose exec allocates a TTY.
在 Windows 上使用 PowerShell 对我有用。【参考方案2】:
对于docker run
不要使用-it
标志
(如 BMitch 所说)
这并不完全符合您的要求,但对其他人也有用:
对于docker-compose exec
使用-T
标志!
-T 键 将帮助使用 docker-compose exec! 的人(它禁用伪 tty 分配)
例如:
docker-compose -f /srv/backend_bigdata/local.yml exec -T postgres backup
或
docker-compose exec -T mysql mysql -uuser_name -ppassword database_name < dir/to/db_backup.sql
【讨论】:
正是我所需要的。根据帮助: -T 禁用伪tty分配。默认情况下,docker-compose exec
分配一个 TTY。
在 mysql 虚拟机上运行 MySQL 数据库(使用上面建议的 -T):docker-compose exec -T mysql mysql -uuser_name -ppassword database_name < dir/to/db_backup.sql
我希望我能再次投票给这个答案......【参考方案3】:
对于那些在 Windows 上遇到此错误和 git bash 的人,只需使用 -it
完美运行的 PowerShell。
【讨论】:
这没有回答问题。问题是关于 Jenkins 中的 docker,而不是 Windows 上的 git bash。 好吧。是的,而且它从未打算这样做。当您搜索此特定错误消息时,该问题会在 google 中弹出。我想,得到答案某处总比没有答案好。显然有些人觉得它很有用:) 将 Powershell 作为 TTY 进行 shell 操作的问题在于它不能正确传递箭头键,例如循环命令历史的向上箭头。除了这个缺点之外,效果很好。 如果你想继续使用Git Bash,见this answer on another question或the winpty answer below 它帮助了我,非常感谢你,我竖起大拇指。【参考方案4】:如果你(和我一样)在 windows 上使用 git bash,你只需要把
winpty
在您的“码头线”之前:
winpty docker exec -it some_cassandra bash
【讨论】:
如何下载winpty
?
问之前有没有试过?我认为它是 Git 自带的(我的在里面 .../Git/usr/bin)
你说得对,它在C:\Program Files\Git\usr\bin\winpty.exe
下【参考方案5】:
为了让 docker 分配一个 TTY(-t
选项),当调用 docker run 时,您已经需要在一个 TTY 中。 Jenkins 不是在 TTY 中执行其作业。
话虽如此,您在 Jenkins 中运行的脚本您可能还想在本地运行。在这种情况下,分配一个 TTY 非常方便,这样您就可以在本地运行时发送 ctrl+c 之类的信号。
要解决此问题,请让您的脚本有选择地使用 -t
选项,如下所示:
test -t 1 && USE_TTY="-t"
docker run $USE_TTY ...
【讨论】:
这个错误发生在我运行docker run…
命令表单由git钩子触发的makefile任务时
这应该是公认的答案。它实际上以普遍适用的方式解决了问题【参考方案6】:
当使用“git bash”时,
1) 我执行命令:
docker exec -it 726fe4999627 /bin/bash
我有错误:
the input device is not a TTY. If you are using mintty, try prefixing the command with 'winpty'
2) 然后,我执行命令:
winpty docker exec -it 726fe4999627 /bin/bash
我还有一个错误:
OCI runtime exec failed: exec failed: container_linux.go:344: starting container process caused "exec: \"D:/Git/usr/bin/
bash.exe\": stat D:/Git/usr/bin/bash.exe: no such file or directory": unknown
3) 第三,我执行:
winpty docker exec -it 726fe4999627 bash
成功了。
当我使用“powershell”时,一切正常。
【讨论】:
用 bash 将我的头撞到了墙上几个小时。切换到 Powershell,现在一切正常! (2) 失败,因为winpty
将类 unix 文件路径的参数转换为 Windows 语言。要清楚地看到这一点:winpty echo "/foo/bar"
打印 C:/Program Files/Git/foo/bar
。
您可以使用MSYS_NO_PATHCONV=1
关闭此行为【参考方案7】:
使用 docker-compose exec -T 通过 Jenkins 为我解决了这个问题
docker-compose exec -T containerName php script.php
【讨论】:
这项工作也在 github 上使用 docker compose 进行操作。谢谢【参考方案8】:如果使用 Windows,请尝试使用 cmd ,对我来说它可以工作。检查docker是否启动。
【讨论】:
【参考方案9】:下面显示的我的 Jenkins 管道步骤失败并出现同样的错误。
steps
echo 'Building ...'
sh 'sh ./Tools/build.sh'
在我的“build.sh”脚本文件中,“docker run”命令在 Jenkins 作业执行时会输出此错误。但是,当脚本在 shell 终端中运行时,它工作正常。错误发生的原因是 -t 选项传递给 docker run 命令,该命令为我知道尝试分配终端,如果没有要分配的终端就会失败。
就我而言,我已将脚本更改为仅在可以检测到终端时才通过 -t 选项。这是修改后的代码:
DOCKER_RUN_OPTIONS="-i --rm"
# Only allocate tty if we detect one
if [ -t 0 ] && [ -t 1 ]; then
DOCKER_RUN_OPTIONS="$DOCKER_RUN_OPTIONS -t"
fi
docker run $DOCKER_RUN_OPTIONS --name my-container-name my-image-tag
【讨论】:
我喜欢你的回答,但如果没有检测到 TTY,我会默认使用DOCKER_RUN_OPTIONS="--rm"
,因为 Jenkins 不需要 -i
。【参考方案10】:
我知道这不是直接回答手头的问题,而是针对使用 WSL 运行 Docker for windows 和 cmder 或 conemu 的任何人。
诀窍是不要使用安装在 Windows 上的 /mnt/c/Program Files/Docker/Docker/resources/bin/docker.exe 的 Docker,而是安装 ubuntu/linux Docker。值得指出的是,您不能从 WSL 中运行 Docker 本身,但您可以从 linux Docker 客户端连接到 Docker for windows。
在 Linux 上安装 Docker
sudo apt-get install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt-get update
sudo apt-get install docker-ce
在端口 2375 上连接到 Docker for windows,这需要从 docker for windows 中的设置中启用。
docker -H localhost:2375 run -it -v /mnt/c/code:/var/app -w "/var/app" centos:7
或者设置 docker_host 变量,这将允许您省略 -H 开关
export DOCKER_HOST=tcp://localhost:2375
您现在应该能够与 tty 终端会话进行交互连接。
【讨论】:
【参考方案11】:只要您不指定要挂载的卷,例如“.:/mountpoint”或“$pwd:/mountpoint”,winpty 就可以工作
我发现的最佳解决方法是使用 Visual Code Studio 中的 git-bash 插件,并使用终端启动和停止容器或 docker-compose。
【讨论】:
【参考方案12】:在 Jenkins 中,我使用的是 docker-compose exec -T
例如:-
docker-compose exec -T app php artisan migrate
【讨论】:
【参考方案13】:对于那些使用Pyinvoke 的人,请参阅this documentation,如果链接失效,我将在此处进行联合:
在 99% 的情况下,将 pty=True 添加到您的运行调用将使事情按您的预期工作。继续阅读为什么会这样(以及为什么 pty=True 不是默认设置)。
命令行程序通常会根据控制终端是否存在而改变行为;一个常见的例子是使用或不使用彩色输出。当输出的接收者是终端上的人时,您可能需要使用颜色、调整线长以匹配终端宽度等。
相反,当您的输出被发送到另一个程序(shell 管道、CI 服务器、文件等)时,颜色转义码和其他特定于终端的行为可能会导致不需要的垃圾。
Invoke 的用例涵盖上述两种情况——有时您只想直接显示数据,有时您只想将其捕获为字符串;通常你想要两者。正因为如此,没有“正确”的默认行为:使用伪终端 - 无论哪种方式,一些大块的用例都会带来不便。
对于不关心的用例,不带伪终端的直接调用更快更简洁,因此是默认设置。
【讨论】:
以上是关于错误“输入设备不是 TTY”的主要内容,如果未能解决你的问题,请参考以下文章
使用 grunt-shell 调用调用 docker run 的脚本时如何解决“输入设备不是 TTY”?
远程服务器返回错误: 404错误远程服务器返回错误:500错误 HttpWebResponse远程服务器返回错误:(404500) 错误。
Pig 安装错误:错误 pig.Main:错误 2998:未处理的内部错误