错误“输入设备不是TTY”

我正在从我的Jenkinsfile运行以下命令。然而,我得到错误"输入设备不是TTY"

docker run -v $PWD:/foobar -it cloudfoundry/cflinuxfs2 /foobar/script.sh

有没有一种方法可以在不进行交互模式的情况下从Jenkinsfile运行脚本?

我基本上有一个名为script.sh的文件,我想在Docker容器中运行它。

546487 次浏览

从cli中删除-it以使其非交互式并删除TTY。如果您不需要,例如在Jenkins或cron脚本中运行您的命令,您应该这样做。

或者,如果您在docker命令中输入的输入不是来自TTY,您可以将其更改为-i。如果您的命令行中有类似xyz | docker ...docker ... <input的内容,请执行此操作。

或者,如果您想要TTY支持但在输入设备上不可用,您可以将其更改为-t。对于检查TTY以启用日志中输出的颜色格式的应用程序,或者当您稍后使用适当的终端连接到容器时,请执行此操作。

或者,如果您需要一个交互式终端,并且没有在Linux或MacOS上的终端中运行,请使用不同的命令行界面。


什么是TTY?它是一个终端接口,支持转义序列,移动光标等,来自于过去连接到大型机的哑终端。今天它由Linux命令终端和ssh接口提供。请参阅维基百科文章了解更多详情

要查看使用和不使用TTY运行容器的区别,请运行没有TTY的容器:docker run --rm -i ubuntu bash。从该容器内部,使用apt-get update; apt-get install vim安装vim。请注意缺少提示。针对文件运行vim时,请尝试在文件中移动光标。

对于那些在Windows上遇到此错误和git bash的人,只需使用-it完美工作的PowerShell。

为了让docker分配一个TTY(-t选项),当调用docker run时,您已经需要在TTY中。Jenkins在TTY中执行其作业没有

话虽如此,您正在运行的脚本Jenkins您可能还想在本地运行。在这种情况下,分配一个TTY非常方便,这样您就可以在本地运行它时发送ctrl+c之类的信号。

要解决此问题,请选择使用-t选项,如下所示:

test -t 1 && USE_TTY="-t"docker run ${USE_TTY} ...

如果使用windows,请尝试使用cmd,对我来说它有效。检查docker是否启动。

如果你(像我一样)在Windows上使用git bash,你只需要把

winpty

在您的“docker line”之前:

winpty docker exec -it some_cassandra bash

只要您不指定要挂载的卷(例如.:/mountpoint${pwd}:/mountpoint),winpty就可以工作

我发现的最好的解决方法是在Visual Code Studio中使用git-bash插件并使用终端启动和停止containersdocker-compose

我知道这不是直接回答手头的问题,但对于任何遇到这个问题的人来说,他们正在使用WSL为Windows和cmder或conemu运行Docker。

诀窍是不要使用安装在Windows上的Docker /mnt/c/ProgramFiles/Docker/Docker/资源/bin/docker.exe而是安装ubuntu/linux Docker。值得指出的是,您不能从WSL中运行Docker本身,但您可以从linux Docker客户端连接到Docker for windows。

在Linux上安装Docker

sudo apt-get install apt-transport-https ca-certificates curl software-properties-commoncurl -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 updatesudo 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终端会话交互连接。

使用'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时,一切都很好。

对于docker run不要使用-it标志

(如BMitch所说)

这并不是你所要求的,但对其他人也很有用:

docker-compose exec使用-T标志!

-t键将帮助使用docker编写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

下面显示的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 oneif [ -t 0 ] && [ -t 1 ]; thenDOCKER_RUN_OPTIONS="$DOCKER_RUN_OPTIONS -t"fi
docker run $DOCKER_RUN_OPTIONS --name my-container-name  my-image-tag

使用docker-compose exec-T通过Jenkins为我修复了问题

docker组成exec-T容器名称phpscript.php

在Jenkins,我使用docker-compose exec-T

eg:-

docker-compose exec -T app php artisan migrate

对于那些使用皮因诺克的人,请参阅这个留档,我将在这里联合起来,以防链接死亡:

99%的情况下,将pty=True添加到您的运行调用将使事情按您期望的方式工作。继续阅读为什么会这样(以及为什么pty=True不是默认值)。

命令行程序通常会根据是否存在控制终端而改变行为;一个常见的例子是使用或停用彩色输出。当输出的接收者是终端上的人时,您可能希望使用颜色、定制行长度以匹配终端宽度等。

相反,当您的输出被发送到另一个程序(shell管道、CI服务器、文件等)时,颜色转义码和其他特定于终端的行为可能会导致不需要的垃圾。

调用的用例跨越了上述两者——有时你只想直接显示数据,有时你只想将其捕获为字符串;通常你想要两者兼而有之。正因为如此,没有“正确”的默认行为re: use的伪终端——一些大块的用例无论哪种方式都不方便。

对于不关心的用例,没有伪终端的直接调用更快、更干净,所以它是默认的。

同样的情况在这里,我正在运行以下命令,即抛. sh脚本(bash)和python. py但是,我得到了相同的错误“输入设备不是TTY”。

在我的情况下,我试图从我的“生产”env的运行容器中获取转储,并使用身份验证和一些参数传递,然后取我的mssql数据库容器. bak文件的输出。

从命令中删除-it。如果您想保持它的交互性,请保留-i

您可以检查我的. sh文件和一个长命令转储。输入图片描述

只使用-i标志而不是-it标志。这可以帮助你看到容器内部发生了什么。

docker exec -i $USER bash <<EOFapt install nano -yEOF

您可能会看到警告,但它会显示您在docker内的终端上的输出。