"डॉक रन" आउटपुट में "इनपुट डिवाइस एक TTY नहीं है" वास्तव में क्या मतलब है?


18

यह एक कमांड है जो काम करता है:

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

यह एक कमांड है जो एक त्रुटि संदेश के साथ प्रतिक्रिया करता है:

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

मैं यह पता लगाना चाहूंगा कि यहां क्या होता है। न केवल "निकालें -t और इसे ठीक किया जाएगा"।

मुझे पता है कि docker runके -tविकल्प "का आवंटन एक छद्म TTY" के लिए खड़ा है, और मैं पढ़ लिया है क्या TTY के लिए खड़ा के ऐतिहासिक अवलोकन , लेकिन यह मदद नहीं की मुझे समझने की क्या एक अनुबंध की तरह यहां का उल्लंघन किया है।


यह बेमानी नहीं है, डॉकटर इसमें कुछ भी संलग्न किए बिना एक TTY बना सकता है। आपके आउटपुट में रंग आदि के लिए वर्ण होंगे, लेकिन आपके टर्मिनल आउटपुट को कंटेनर के इनपुट में नहीं डाला जाएगा। तो आपके द्वारा टाइप किए जाने वाले अक्षर अगले कमांड के लिए पंक्तिबद्ध होंगे जिन्हें आप docker कमांड के बाहर निकलने के बाद चलाते हैं।
BMitch

क्या मैं डॉकटर के भीतर ट्टी शुरू कर सकता हूं? मेरे पास कुछ ऐप हैं, जो काम करना बंद कर देते हैं, मैं डॉक करने वाले के साथ नहीं चलता -t, लेकिन मैं प्रोडक्शन में डॉक स्टार्ट कमांड को संशोधित नहीं कर सकता। इसलिए मुझे लगता है कि ऐप को बनाने की जरूरत है क्योंकि यह इसके साथ शुरू किया गया था -t
मावेरेसेक

जवाबों:


9

इस उत्तर ने मुझे अपना सिर लपेटने में मदद की:

  • डिफ़ॉल्ट (बिना न तो द्वारा -iऔर न ही -tविकल्प) एक डोकर कंटेनर केवल STDOUT करने के लिए इसके उत्पादन भेजता है,
  • -iविकल्प के साथ STDIN का कनेक्शन आता है,
  • -tविकल्प एक टर्मिनल इंटरफ़ेस ड्राइवर में खींचता है , जो STDIN / STDOUT के शीर्ष पर काम करता है। और जब एक टर्मिनल ड्राइवर को खींचा जाता है, तो कंटेनर के साथ संचार टर्मिनल इंटरफ़ेस प्रोटोकॉल के अनुरूप होना चाहिए । एक स्ट्रिंग पाइपिंग नहीं करता है।

7

देर से जवाब, लेकिन किसी की मदद कर सकते हैं

docker run/exec -iकंटेनर के अंदर कमांड के STDIN को docker run/execखुद के STDIN से जोड़ेगा ।

इसलिए

  • docker run -i alpine catआपको इनपुट के लिए एक खाली लाइन देता है। टाइप करें "हैलो" आपको एक प्रतिध्वनि "हैलो" मिलती है। कंटेनर तब तक बाहर नहीं निकलेगा जब तक आप CTRL + D नहीं भेजते हैं क्योंकि मुख्य प्रक्रिया catअनंत स्ट्रीम से इनपुट का इंतजार कर रही है, जिसका टर्मिनल इनपुट है docker run
  • दूसरी ओर echo "hello" | docker -i run alpine cat"हैलो" प्रिंट करेगा और तुरंत बाहर निकल जाएगा क्योंकि catनोटिस कि इनपुट स्ट्रीम समाप्त हो गया है और खुद को समाप्त कर देता है।

यदि आप docker psउपरोक्त दोनों में से किसी एक से बाहर निकलने के बाद कोशिश करते हैं, तो आपको कोई भी चलने वाला कंटेनर नहीं मिलेगा। दोनों ही मामलों में, catखुद को समाप्त कर दिया है, इस प्रकार डॉकटर ने कंटेनर को समाप्त कर दिया है।

अब "-t" के लिए, यह डॉकटर के अंदर मुख्य प्रक्रिया को बताता है कि इसका इनपुट एक टर्मिनल डिवाइस है।

इसलिए

  • docker run -t alpine catआपको एक खाली रेखा देगा, लेकिन यदि आप "हैलो" टाइप करने का प्रयास करते हैं, तो आपको कोई प्रतिध्वनि नहीं मिलेगी। ऐसा इसलिए है क्योंकि जब catआप किसी टर्मिनल इनपुट से जुड़े होते हैं, तो यह इनपुट आपके इनपुट से जुड़ा नहीं होता है। आपके द्वारा टाइप किया गया "हैलो" इनपुट तक नहीं पहुंचा catcatउस इनपुट की प्रतीक्षा कर रहा है जो कभी नहीं आता है।
  • echo "hello" | docker run -t alpine cat आपको एक खाली लाइन भी देगा और CTRL-D पर कंटेनर से बाहर नहीं निकलेगा, लेकिन आपको एक "हैलो" नहीं मिलेगा, क्योंकि आप पास नहीं हुए हैं -i

यदि आप CTRL + C भेजते हैं, तो आपको अपना शेल वापस मिल जाता है, लेकिन यदि आप docker psअभी कोशिश करते हैं, तो आप catकंटेनर को अभी भी देखते हैं । ऐसा इसलिए है क्योंकि catअभी भी एक इनपुट स्ट्रीम पर प्रतीक्षा की जा रही है जो कभी बंद नहीं हुई थी। मुझे -tअकेले संयुक्त किए बिना कोई उपयोगी उपयोग नहीं मिला -i

अब, -itएक साथ के लिए। यह बिल्ली को बताता है कि उसका इनपुट एक टर्मिनल है और उसी समय में इस टर्मिनल को उस इनपुट से कनेक्ट करें, docker runजो एक टर्मिनल है। docker run/execयह सुनिश्चित कर लेगा कि इसका अपना इनपुट वास्तव में इसे पास करने से पहले एक tty है cat। यही कारण है कि input device is not a TTYयदि आप कोशिश करेंगे तो आपको मिलेगा echo "hello" | docker run -it alpine catक्योंकि इस मामले में, docker runस्वयं का इनपुट पिछली प्रतिध्वनि से पाइप है न कि टर्मिनल जहां docker runनिष्पादित होता है

अंत में, आपको पास करने की आवश्यकता क्यों होगी -tयदि -iआपके इनपुट को इनपुट से जोड़ने की ट्रिक आएगी cat? ऐसा इसलिए है क्योंकि अगर यह टर्मिनल है तो कमांड अलग तरीके से इनपुट का उपचार करते हैं। यह भी उदाहरण द्वारा सबसे अच्छा चित्रण किया गया है

  • docker run -e MYSQL_ROOT_PASSWORD=123 -i mariadb mysql -uroot -pआपको एक पासवर्ड प्रॉम्प्ट देगा। यदि आप पासवर्ड टाइप करते हैं, तो अक्षर स्पष्ट रूप से मुद्रित होते हैं।
  • docker run -i alpine shआपको एक खाली लाइन देगा। यदि आप एक कमांड टाइप करते हैं जैसे lsआपको आउटपुट मिलता है, लेकिन आपको प्रॉम्प्ट या रंगीन आउटपुट नहीं मिलेगा।

पिछले दो मामलों में, आपको यह व्यवहार मिलता है क्योंकि mysqlसाथ ही shellइनपुट को टिट्टी के रूप में नहीं मान रहे थे और इस प्रकार इनपुट को मास्क करने या आउटपुट को रंग देने जैसे छोटे विशिष्ट व्यवहार का उपयोग नहीं किया था।


4

ट्टी इंगित करता है कि आपके पास एक टर्मिनल है, कुछ ऐसा जिसे xterm या कई लाइन कमांड लाइन इंटरफेस में से एक द्वारा प्रदान किया जाएगा। इसके साथ एक कीबोर्ड और टेक्स्ट आउटपुट इंटरफ़ेस की आवश्यकता होती है। ऐसा करने के लिए विशिष्ट कारण रंग पाठ आउटपुट समर्थन, विभिन्न कुंजी संयोजनों (जैसे तीर कुंजी) से निपटने और स्क्रीन के चारों ओर कर्सर को स्थानांतरित करने की क्षमता के लिए है।

जब आप अपने echoउदाहरण से पता चलता है कि पाइप एक कमांड को पाइप करता है, तो वह पाइप इनपुट है, और उस पाइप में एक छोटा इंटरफ़ेस नहीं है, यह सिर्फ पाठ की एक धारा है। त्रुटि संदेश इंगित करता है के साथ एक tty बनाने का प्रयास विफल हो जाएगा।


इसे भी देखें: stackoverflow.com/a/43099210/596285
BMitch

"कीबोर्ड और आउटपुट इंटरफ़ेस" और "STDIN / STDOUT" के बीच मेरे लिए अभी भी एक अंतर है। स्पष्ट रूप से आप STDOUT में "कर्सर स्थिति" अवधारणा को लागू नहीं कर सकते, क्योंकि STDOUT एक धारा है, स्क्रीन नहीं। एसटीडीयूएसटी के शीर्ष पर आउटपुट इंटरफ़ेस एब्स्ट्रैक्शन के बारे में क्या विनिर्देश हैं (मुझे लगता है कि) है?
मिखाइल वासिन

1
यह एक इंटरफ़ेस है जो स्टडिन / स्टडआउट के शीर्ष पर चलता है। en.wikipedia.org/wiki/POSIX_terminal_interface
BMitch
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.