我正在Jenkinsfile中运行以下命令。然而,我收到错误“输入设备不是TTY”。
docker run -v $PWD:/foobar -it cloudfoundry/cflinuxfs2 /foobar/script.sh
有没有一种方法可以在不进行交互模式的情况下从Jenkinsfile运行脚本?
我基本上有一个名为script.sh的文件,我想在Docker容器中运行。
我正在Jenkinsfile中运行以下命令。然而,我收到错误“输入设备不是TTY”。
docker run -v $PWD:/foobar -it cloudfoundry/cflinuxfs2 /foobar/script.sh
有没有一种方法可以在不进行交互模式的情况下从Jenkinsfile运行脚本?
我基本上有一个名为script.sh的文件,我想在Docker容器中运行。
从cli中删除-it以使其非交互式,并删除TTY。如果您不需要,例如在Jenkins或cron脚本中运行命令,那么应该这样做。
或者,如果输入管道连接到docker命令,而不是来自TTY,则可以将其更改为-i。如果你有类似xyz|docker的东西。。。或码头工人<在命令行中输入,执行此操作。
或者,如果您希望TTY支持,但输入设备上没有TTY,则可以将其更改为-t。对于检查TTY以启用日志中输出的颜色格式的应用程序,或者当您稍后使用适当的终端连接到容器时,请执行此操作。
或者,如果您需要一个交互式终端,而不是在Linux或MacOS上的终端上运行,请使用不同的命令行界面。据报告,PowerShell在Windows上包含此支持。
什么是TTY?这是一个终端界面,支持转义序列、移动光标等,这源于以前连接到大型机的哑终端。今天,它由Linux命令终端和ssh接口提供。有关详细信息,请参阅维基百科文章。
要了解使用和不使用TTY运行容器的区别,请运行没有TTY的容器:docker run--rm-i ubuntu bash。从容器内部,安装带有apt-get-update的vim;apt-get安装vim。注意缺少提示。当对文件运行vim时,尝试在文件内移动光标。
为了让docker分配TTY(-t选项),当docker运行被调用时,您已经需要在TTY中。Jenkins不在TTY中执行其任务。
话虽如此,您在Jenkins中运行的脚本可能也希望在本地运行。在这种情况下,分配TTY非常方便,这样在本地运行时就可以发送类似ctrl+c的信号。
要解决此问题,请使脚本可以选择使用-t选项,如下所示:
test -t 1 && USE_TTY="-t"
docker run ${USE_TTY} ...
如果您在windows上使用gitbash,只需将
冬季的
在“码头线”之前:
winpty docker exec -it some_container bash
只要不指定要装载的卷(例如.:/mountpoint或${pwd}:/mountpoint
我找到的最佳解决方法是在Visual Code Studio中使用git bash插件,并使用终端启动和停止容器或docker compose。
我知道这并不是直接回答眼前的问题,而是针对使用WSL运行Docker for windows和cmder或conemu的人。
诀窍不在于使用安装在windows上的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运行-it-v/mnt/c/code:/var/app-w“/var/app”centos:7
或者设置docker_host变量,这样可以省略-H开关
导出DOCKER_HOST=tcp://localhost:2375
现在您应该能够与tty终端会话交互连接。
使用“gitbash”时,
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运行DON NOT USE-it标志
(如BMitch所述)
这并不完全是你所要求的,但对其他人也很有用:
对于docker compose exec,使用-T标志!
-T键将帮助使用docker的人编写exec!(它禁用伪tty分配)
例如:
docker-compose -f /srv/backend_bigdata/local.yml exec -T postgres backup
or
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 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
使用docker compose exec-T通过Jenkins为我解决了这个问题
docker compose exec-T containerName php script.php
在詹金斯,我使用docker compose exec-T
eg:-
docker-compose exec -T app php artisan migrate
对于使用Pyinvoke的用户,请参阅以下文档,如果链接失效,我将在这里联合这些文档:
99%的情况下,将pty=True添加到您的跑步通话中会使事情按照您的预期进行。继续阅读原因(以及为什么pty=True不是默认值)。
命令行程序经常根据控制终端是否存在而改变行为;一个常见的例子是彩色输出的使用或废弃。当输出的接收者是终端上的人时,您可能需要使用颜色、调整线路长度以匹配终端宽度等。
相反,当您的输出被发送到另一个程序(shell管道、CI服务器、文件等)时,颜色转义码和其他特定于终端的行为可能会导致无用的垃圾。
Invoke的用例涵盖了以上两种情况——有时您只希望直接显示数据,有时您只想将其捕获为字符串;通常你都想要。因此,没有“正确”的默认行为:使用伪终端——无论哪种方式都会给大量用例带来不便。
对于不关心的用例,没有伪终端的直接调用更快、更干净,因此它是默认的。
同样的情况在这里,我运行以下命令throw.sh脚本(bash)和python.py然而,我得到了同样的错误“输入设备不是TTY”。
在我的例子中,我试图通过身份验证从“production”env的运行容器中获取转储,并传递一些参数,然后获取mssql数据库容器的.bak文件的输出。
从命令中删除-it。如果你想保持它的交互性,那么就保持-i。
您可以检查我的.sh文件和一个获取转储的长命令。
只使用-i标志而不是-it标志。这可以帮助您了解容器内的情况。
docker exec -i $USER bash <<EOF
apt install nano -y
EOF
您可能会看到警告,但它显示了docker内部终端上的输出。
而不是使用-it使用--tty
所以你的docker运行应该是这样的:
docker run -v $PWD:/foobar --tty cloudfoundry/cflinuxfs2 /foobar/script.sh