错误"输入设备不是TTY"

时间:2017-03-29 16:26:15

标签: docker jenkins jenkins-pipeline

我从Jenkinsfile运行以下命令。但是,我收到错误"输入设备不是TTY"

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

有没有办法在不进行交互模式的情况下从Jenkinsfile运行脚本?

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

13 个答案:

答案 0 :(得分:390)

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

或者,如果您输入的管道输入管道命令并非来自TTY,您可以将其更改为-i。如果您的命令行中有xyz | docker ...docker ... <input,请执行此操作。

或者,如果您需要TTY支持但未在输入设备上使用,则可以将其更改为-t。这样做是为了对日志中的输出进行颜色格式化,或者以后用适当的终端连接到容器时。

或者,如果您需要交互式终端并且未在Linux或MacOS上的终端中运行,请使用其他命令行界面。据报道,PowerShell在Windows上包含此支持。

什么是TTY?它是一个支持彩色输出,转义序列,移动光标等的终端接口,它来自于连接到大型机的哑终端的旧时代。今天它由Linux命令终端和ssh接口提供。请参阅wikipedia article for more details

答案 1 :(得分:48)

对于那些在Windows上遇到此错误和git bash的人,只需使用import UIKit class ViewController: UITableViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 4 } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "ChecklistItem", for: indexPath) let label = cell.viewWithTag(1000) as! UILabel let image = cell.viewWithTag(1001) as! UIImageView let margins = cell.contentView.layoutMarginsGuide if indexPath.row == 0 { label.text = "First row" } else if indexPath.row == 1 { label.text = "Second row" image.image = UIImage(named: "test") } else if indexPath.row == 2 { label.text = "Third row" label.leadingAnchor.constraint(equalTo: margins.leadingAnchor).isActive = true } else if indexPath.row == 3 { label.text = "Fourth row" } return cell } } 完美运行的PowerShell。

答案 2 :(得分:31)

如果你(就像我)在Windows上使用git bash,你只需要输入

  

winpty

在“泊坞线”之前:

winpty docker exec -it some_cassandra bash

答案 3 :(得分:23)

我相信你需要在TTY中为docker分配一个TTY(-t选项)。 Jenkins在TTY中执行 not 的工作。

话虽如此,您在Jenkins中运行的脚本也可能需要在本地运行。在这种情况下,分配TTY非常方便,因此在本地运行时可以发送 ctrl + c 等信号。

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

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

答案 4 :(得分:21)

这不是您要问的,而是:

-T键将帮助使用 docker-compose exec!

的人。
docker-compose -f /srv/backend_bigdata/local.yml exec -T postgres backup

答案 5 :(得分:4)

使用docker-compose exec -T通过Jenkins为我解决了这个问题

docker-compose exec -T containerName php script.php

答案 6 :(得分:3)

如果使用Windows,请尝试使用cmd,对我来说它可行。检查docker是否已启动。

答案 7 :(得分:1)

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

我发现最好的解决方法是使用Visual Code Studio中的git-bash插件,并使用终端启动和停止容器或docker-compose。

答案 8 :(得分:1)

我知道这不是直接回答当前的问题,而是针对任何遇到此问题的人,这些人正在使用WSL在Windows和cmder或conmumu上运行Docker。

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

在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上连接到Windows的Docker,需要从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终端会话进行交互式连接。

答案 9 :(得分:0)

使用“ 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”时,一切正常。

答案 10 :(得分:0)

下面显示的我的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

答案 11 :(得分:0)

在詹金斯,我使用 docker-compose exec -T

例如:-

docker-compose exec -T app php artisan migrate

答案 12 :(得分:0)

对于那些使用 Pyinvoke 的人,请参阅 this documentation,万一链接失效,我将在此处联合:

<块引用>

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

<块引用>

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

<块引用>

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

<块引用>

Invoke 的用例涵盖了以上两种情况——有时您只想直接显示数据,有时您只想将其捕获为字符串;通常你两者都想要。正因为如此,没有“正确”的默认行为:使用伪终端——无论哪种方式都会给一些大量用例带来不便。

<块引用>

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