O que “o dispositivo de entrada não é um TTY” significa exatamente na saída “docker run”?

18

Este é um comando que funciona:

$ echo 'hi there' | docker run -i ubuntu cat
hi there

Este é um comando que responde com uma mensagem de erro:

$ echo 'hi there' | docker run -it ubuntu cat
the input device is not a TTY

Eu gostaria de descobrir exatamente o que acontece aqui. Não apenas "remova -t e será corrigido".

Eu sei que docker run's -topção significa 'Alocar um pseudo-TTY', e eu li resumos históricos de que TTY significa , mas não me ajudar a compreender que tipo de contrato é violado aqui.

Mikhail Vasin
fonte
Não é redundante, o docker pode criar um TTY sem anexar nada a ele. Sua saída teria caracteres para cores, etc., mas a saída do terminal não seria canalizada para a entrada do contêiner. Portanto, os caracteres digitados seriam colocados na fila para o próximo comando executado após a saída do comando docker.
21418 BMitch
Posso iniciar o tty na janela de encaixe? Tenho um aplicativo que para de funcionar e não executo a janela de encaixe -t, mas não consigo modificar o comando docker start em produção. Então, preciso fazer com que o aplicativo pense que foi iniciado -t.
mvorisek

Respostas:

9

Essa resposta me ajudou a entender:

  • por padrão (sem opções -inem -topções), um contêiner do Docker envia apenas sua saída para STDOUT,
  • com -iopção vem conexão com STDIN,
  • -tA opção puxa um driver de interface de terminal , que funciona em cima de STDIN / STDOUT. E quando um driver de terminal é acionado, a comunicação com um contêiner deve estar em conformidade com o protocolo da interface do terminal . Tubulação de uma cadeia não.
Mikhail Vasin
fonte
7

Resposta tardia, mas pode ajudar alguém

docker run/exec -iconectará o STDIN do comando dentro do contêiner ao STDIN do docker run/execpróprio.

então

  • docker run -i alpine catfornece uma linha vazia aguardando entrada. Digite "olá" para obter um eco "olá". O contêiner não sairá até você enviar CTRL + D porque o processo principal catestá aguardando a entrada do fluxo infinito que é a entrada do terminal docker run.
  • Por outro lado echo "hello" | docker -i run alpine cat, imprimirá "olá" e sairá imediatamente, porque catpercebe que o fluxo de entrada terminou e termina automaticamente .

Se você tentar docker psdepois de sair de qualquer um dos itens acima, não encontrará nenhum contêiner em execução. Nos dois casos, catele próprio foi finalizado, portanto, a janela de encaixe finalizou o contêiner.

Agora, para "-t", isso diz ao processo principal dentro da janela de encaixe que sua entrada é um dispositivo terminal.

então

  • docker run -t alpine catfornecerá uma linha vazia, mas se você tentar digitar "olá", não receberá eco. Isso ocorre porque enquanto catestiver conectado a uma entrada do terminal, essa entrada não estará conectada à sua entrada. O "olá" que você digitou não atingiu a entrada de cat. catestá aguardando uma entrada que nunca chega.
  • echo "hello" | docker run -t alpine cat também fornecerá uma linha vazia e não sairá do contêiner no CTRL-D, mas você não receberá um "alô" de eco porque não passou -i

Se você enviar CTRL + C, recupera seu shell, mas se tentar docker psagora, verá o catcontêiner ainda em execução. Isso ocorre porque catainda está aguardando um fluxo de entrada que nunca foi fechado. Eu não encontrei nenhum uso útil para o -tsozinho, sem ser combinado com -i.

Agora, -itjuntos. Isso informa ao gato que sua entrada é um terminal e ao mesmo tempo conecta esse terminal à entrada da docker runqual é um terminal. docker run/execgarantirá que sua própria entrada seja realmente um tty antes de passá-la para cat. É por isso que você obterá um input device is not a TTYse tentar, echo "hello" | docker run -it alpine catporque nesse caso, a entrada em docker runsi é o canal do eco anterior e não o terminal onde docker runé executado

Por fim, por que você precisaria passar -tse -ifará o truque de conectar sua entrada à catentrada de? Isso ocorre porque os comandos tratam a entrada de maneira diferente se for um terminal. Isso também é melhor ilustrado pelo exemplo

  • docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -uroot -pfornecerá uma solicitação de senha. Se você digitar a senha, os caracteres serão impressos visivelmente.
  • docker run -i alpine shlhe dará uma linha vazia. Se você digitar um comando como lsobtém uma saída, mas não receberá uma saída rápida ou colorida.

Nos dois últimos casos, você tem esse comportamento porque mysql, assim como shellnão estavam tratando a entrada como um tty e, portanto, não utilizar tty comportamento específico como mascarar a entrada ou colorir a saída.

Ahmed Ghonim
fonte
4

Um tty indica que você possui um terminal, algo que seria fornecido pelo xterm ou por uma das muitas interfaces de linha de comando do linux. Ele precisa de uma interface de saída de teclado e texto associada a ele. Os motivos típicos para isso são o suporte à saída de texto colorido, o manuseio de várias combinações de teclas (como as teclas de seta) e a capacidade de mover o cursor pela tela.

Quando você canaliza um comando na janela de encaixe, como echomostra o exemplo, esse canal é a entrada e esse canal não possui uma interface tty, é apenas um fluxo de texto. A tentativa de criar um tty com isso falhará como a mensagem de erro indica.

BMitch
fonte
Ainda existe uma diferença entre "um teclado e uma interface de saída" e "STDIN / STDOUT". Obviamente, você não pode aplicar o conceito de "posição do cursor" ao STDOUT, pois STDOUT é um fluxo, não uma tela. Quais especificações descrevem a abstração da interface de saída que (eu acho) é sobre STDOUT?
Mikhail Vasin
1
É uma interface que roda sobre stdin / stdout. pt.wikipedia.org/wiki/POSIX_terminal_interface
BMitch 19/02