Apa arti "perangkat input bukan TTY" sebenarnya dalam output "docker run"?

18

Ini adalah perintah yang berfungsi:

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

Ini adalah perintah yang merespons dengan pesan kesalahan:

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

Saya ingin mencari tahu apa yang terjadi di sini. Bukan hanya "hapus -t dan itu akan diperbaiki".

Aku tahu bahwa docker run's -tpilihan singkatan dari 'Mengalokasikan pseudo-TTY', dan saya telah membaca ikhtisar sejarah apa TTY singkatan , tapi itu tidak membantu saya memahami jenis kontrak dilanggar di sini.

Mikhail Vasin
sumber
Itu tidak berlebihan, buruh pelabuhan dapat membuat TTY tanpa melampirkan apa pun padanya. Output Anda akan memiliki karakter untuk warna, dll, tetapi output terminal Anda tidak akan disalurkan ke input wadah. Jadi karakter yang Anda ketik akan antri untuk perintah berikutnya yang Anda jalankan setelah perintah buruh pelabuhan keluar.
BMitch
Bisakah saya memulai tty di dalam buruh pelabuhan? Saya memiliki beberapa aplikasi yang berhenti bekerja dengan saya tidak menjalankan buruh pelabuhan dengan -t, tetapi saya tidak dapat memodifikasi perintah mulai buruh pelabuhan dalam produksi. Jadi saya perlu membuat aplikasi berpikir itu dimulai dengan -t.
mvorisek

Jawaban:

9

Jawaban ini membantu saya merangkul:

  • secara default (tanpa keduanya -iatau -topsi) wadah Docker hanya mengirimkan hasilnya ke STDOUT,
  • dengan -iopsi datang koneksi ke STDIN,
  • -topsi menarik driver antarmuka terminal , yang bekerja di atas STDIN / STDOUT. Dan ketika driver terminal ditarik, komunikasi dengan kontainer harus sesuai dengan protokol antarmuka terminal . Perpipaan string tidak.
Mikhail Vasin
sumber
7

Jawaban terlambat, tetapi mungkin membantu seseorang

docker run/exec -iakan menghubungkan STDIN dari perintah di dalam wadah ke STDIN docker run/execitu sendiri.

Begitu

  • docker run -i alpine catmemberi Anda garis kosong menunggu input. Ketik "halo" Anda mendapatkan gema "halo". Kontainer tidak akan keluar sampai Anda mengirim CTRL + D karena proses utama catsedang menunggu input dari aliran tak terbatas yang merupakan input terminal dari docker run.
  • Di sisi lain echo "hello" | docker -i run alpine catakan mencetak "halo" dan segera keluar karena catpemberitahuan bahwa aliran input telah berakhir dan berakhir dengan sendirinya.

Jika Anda mencoba docker pssetelah Anda keluar dari salah satu di atas, Anda tidak akan menemukan wadah berjalan. Dalam kedua kasus, catitu sendiri telah berakhir, sehingga buruh pelabuhan telah mengakhiri wadah.

Sekarang untuk "-t", ini memberitahu proses utama di dalam docker bahwa inputnya adalah perangkat terminal.

Begitu

  • docker run -t alpine catakan memberi Anda baris kosong, tetapi jika Anda mencoba mengetik "halo", Anda tidak akan mendapatkan gema. Ini karena saat catterhubung ke input terminal, input ini tidak terhubung ke input Anda. "Halo" yang Anda ketikkan tidak mencapai input cat. catsedang menunggu input yang tidak pernah tiba.
  • echo "hello" | docker run -t alpine cat juga akan memberi Anda garis kosong dan tidak akan keluar dari wadah di CTRL-D tetapi Anda tidak akan mendapatkan gema "halo" karena Anda tidak lulus -i

Jika Anda mengirim CTRL + C, Anda mendapatkan shell Anda kembali, tetapi jika Anda coba docker pssekarang, Anda melihat catwadah masih berjalan. Ini karena catmasih menunggu aliran input yang tidak pernah ditutup. Saya belum menemukan penggunaan yang berguna untuk -tsendirian tanpa digabungkan dengan -i.

Sekarang, untuk -itbersama. Ini memberitahu kucing bahwa inputnya adalah terminal dan pada saat yang sama sambungkan terminal ini ke input docker runyang merupakan terminal. docker run/execakan memastikan bahwa inputnya sendiri sebenarnya tty sebelum meneruskannya cat. Inilah sebabnya mengapa Anda akan mendapatkan input device is not a TTYjika Anda mencoba echo "hello" | docker run -it alpine catkarena dalam kasus ini, input docker runitu sendiri adalah pipa dari gema sebelumnya dan bukan terminal tempat docker rundieksekusi

Akhirnya, mengapa Anda harus lulus -tjika -iakan melakukan trik menghubungkan input Anda ke catinput? Ini karena perintah memperlakukan input secara berbeda jika terminal. Ini juga digambarkan dengan contoh

  • docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -uroot -pakan memberi Anda kata sandi. Jika Anda mengetikkan kata sandi, karakter dicetak dengan jelas.
  • docker run -i alpine shakan memberi Anda garis kosong. Jika Anda mengetik perintah seperti lsAnda mendapatkan output, tetapi Anda tidak akan mendapatkan output berwarna atau prompt.

Dalam dua kasus terakhir, Anda mendapatkan perilaku ini karena mysqljuga shelltidak memperlakukan input sebagai tty dan karenanya tidak menggunakan perilaku spesifik tty seperti menutupi input atau mewarnai output.

Ahmed Ghonim
sumber
4

Sebuah tty menunjukkan Anda memiliki terminal, sesuatu yang akan disediakan oleh xterm atau salah satu dari banyak antarmuka baris perintah linux. Perlu antarmuka keyboard dan output teks yang terkait dengannya. Alasan umum untuk menginginkan ini adalah untuk dukungan output teks berwarna, penanganan berbagai kombinasi tombol (seperti tombol panah), dan kemampuan untuk memindahkan kursor di sekitar layar.

Ketika Anda memipakan perintah ke buruh pelabuhan seperti echocontoh Anda menunjukkan, bahwa pipa adalah input, dan pipa itu tidak memiliki antarmuka tty, itu hanya aliran teks. Mencoba membuat tty dengan itu akan gagal seperti yang ditunjukkan pesan kesalahan.

BMitch
sumber
Masih ada celah bagi saya antara "keyboard dan antarmuka output" dan "STDIN / STDOUT". Jelas Anda tidak dapat menerapkan konsep "posisi kursor" ke STDOUT, karena STDOUT adalah streaming, bukan layar. Apa spesifikasi yang menggambarkan abstraksi antarmuka keluaran yang (saya kira) di atas STDOUT?
Mikhail Vasin
1
Ini adalah antarmuka yang berjalan di atas stdin / stdout. en.wikipedia.org/wiki/POSIX_terminal_interface
BMitch