क्या अन्य कमांड को STDIN में लिखना सुरक्षित है जबकि पिछली कमांड STDOUT को लिख रही है?


21

शायद यह पहले उत्तर दिया गया है, मैं एक और उत्तर के लिए एक लिंक का स्वागत करूंगा ...

अगर मैं bashनिम्नलिखित की तरह एक शेल कमांड (एक शेल में) निष्पादित करता हूं :

make

तब, जबकि उत्पादन से makeसे से स्क्रॉल है STDOUTकी makeकमान, अगर मैं टाइप make checkऔर प्रेस enterसे पहले पहले आदेश, को क्रियान्वित जब समाप्त हो गया है makeआदेश अंत में खत्म अगले आदेश make checkसही ऊपर और चलाने का चुनाव करेगा।

मेरा प्रश्न बस यही है:

  1. क्या ऐसा करना खतरनाक है?
  2. क्या इस तरह की भीड़ टाइपिंग से कोई संभावित अप्रत्याशित व्यवहार होता है?
  3. यह इस तरह से काम क्यों करता है?

2
1. मुझे आशा है कि यह नहीं है ... मैं वर्षों से ऐसा कर रहा हूं!
जॉन डब्ल्यूएच स्मिथ

जवाबों:


20

यह काम करता है जिस तरह से करता है क्योंकि यूनिक्स पूर्ण-द्वैध है। जैसा कि रिची ने यूनिक्स टाइम-शेयरिंग सिस्टम में कहा: ए रेट्रोस्पेक्टिव :

एक चीज जो तुच्छ लगती है, फिर भी एक बार उपयोग करने के बाद एक आश्चर्यजनक अंतर पड़ता है, पूर्ण-द्वैध टर्मिनल I / O एक साथ पढ़ा-आगे है। भले ही प्रोग्राम आम तौर पर एकल वर्णों के बजाय लाइनों के संदर्भ में उपयोगकर्ता के साथ संवाद करते हैं, पूर्ण-द्वैध टर्मिनल I / O का अर्थ है कि उपयोगकर्ता किसी भी समय टाइप कर सकता है, भले ही सिस्टम वापस टाइप कर रहा हो, बिना हार या भय के पात्रों के साथ। । रीड-फॉरवर्ड के साथ, हर लाइन के जवाब का इंतजार नहीं करना चाहिए। दस्तावेज़ में प्रवेश करने वाला एक अच्छा टाइपिस्ट प्रत्येक नई लाइन शुरू करने से पहले रुकने के लिए अविश्वसनीय रूप से निराश हो जाता है; किसी के लिए भी जो जानता है कि वह प्रतिक्रिया में कोई सुस्ती कहना चाहता है मनोवैज्ञानिक रूप से बढ़ जाता है अगर जानकारी को पूरी गति के बजाय बिट-बाय-बिट में दर्ज किया जाना चाहिए।

[अंतिम उद्धरण]

कहा जा रहा है कि, कुछ आधुनिक कार्यक्रम हैं जो किसी भी टाइपहेड को खाते हैं या त्यागते हैं; sshऔर apt-getदो उदाहरण हैं। यदि आप दौड़ते हुए आगे टाइप करते हैं, तो आप पा सकते हैं कि आपके इनपुट का पहला भाग गायब हो गया है। यह एक समस्या हो सकती है।

ssh remotehost do something that takes 20 seconds
mail bob
Dan has retired. Feel free to save any important files and then do
# ssh exits here, discarding the previous 2 lines
rm -fr *
.

तो bash fork()s और execs कमांड के बाद, क्या पहला कमांड अभी भी STDINबैश शेल से जुड़ा हुआ है ? ऐसा लगता है कि जवाब नहीं है, बैश अगले आदेश के लिए बफरिंग प्रतीत होगा। क्या वो सही है?
१११ ---

जब तक आप शेल को कमांड के स्टड को पुनर्निर्देशित करने के लिए नहीं कहते हैं, कमांड में शेल के समान स्टड होगा। आप जो कुछ भी टाइप करते हैं, उसे पढ़ने वाली पहली प्रक्रिया द्वारा पढ़ा जाता है। शेल जानबूझकर कुछ भी पढ़ने की कोशिश नहीं करता है जबकि एक कमांड चल रहा है, और तब तक इंतजार करता है जब तक कि कमांड बंद न हो जाए। यदि आप पृष्ठभूमि के साथ कमांड डालते हैं तो चीजें अधिक जटिल हो जाती हैं &
मार्क प्लॉटनिक

तो STDINएक पाँच तरीके से नियंत्रित किया जाता है? और मुझे लगता है कि जब तक बाश की बाल प्रक्रिया स्पष्ट रूप से अपनी विरासत में मिली फ़ाइल को बंद नहीं करती है STDINतब तक यह अतिरिक्त टाइपिंग से भी पढ़ सकता है ?
१११ ---

हां, सभी टर्मिनल इनपुट को FIFO हैंडल किया जाता है। यकीन नहीं होता कि मैं आपका दूसरा सवाल समझ गया हूं। बच्चे की प्रक्रिया - शेल ने जिस कमांड को लागू किया है - आमतौर पर स्पष्ट रूप से इसकी स्टड को बंद नहीं करता है ; शेल रास्ते से बाहर कदम रखता है और कमांड को वह सब पढ़ने देता है जो वह चाहता है, फिर बच्चा रुक जाता है और शेल पढ़ना शुरू कर देता है।
मार्क प्लॉटनिक

हाँ, आपने मेरे दोनों अनुवर्ती प्रश्नों को बहुत स्पष्ट रूप से संबोधित किया, धन्यवाद!
१११ ---

12

आप जो मूल व्यवहार देख रहे हैं, वह यह है कि इनपुट बफर में तब तक बैठता है जब तक वह पढ़ा नहीं जाता है (ठीक है, यदि आप पर्याप्त लिखते हैं, तो अंततः बफ़र्स भर जाएंगे, और कुछ खो जाएगा, हालांकि यह बहुत टाइपिंग होगा)। ज्यादातर चीजें एसटीडीआईएन से नहीं पढ़ती हैं, इसलिए यह बफर में रहती है।

खतरा यह है कि गलत कमांड आपके इनपुट को पढ़ती है। उदाहरण के लिए, makeकुछ ऐसा है जो आपको संकेत देने का फैसला करता है, और फिर यह आपके अगले आदेश को एक उत्तर के रूप में पढ़ सकता है। कितना खतरनाक है जो कमांड पर निर्भर करता है, निश्चित रूप से। (वे पहले सभी इनपुट को फ्लश कर सकते हैं, बस अपने पिछले इनपुट को छोड़ दें।)

एक कमांड, जिसे आमतौर पर मेकफाइल्स में उपयोग किया जाता है, वह ऐसा कर सकता है जो कि टीएक्स है। यदि यह एक त्रुटि का सामना करता है (और उपयोगकर्ता को संकेत देने के लिए कभी ध्वज नहीं दिया गया है), तो यह संकेत देगा कि आप कैसे जारी रखना चाहते हैं।

एक बेहतर विकल्प शायद चलाना है make && make check:।


8
  1. ठीक है, अर्ध-जाहिर है, आपको एक दूसरी कमांड नहीं चलनी चाहिए जो पहले कमांड पर निर्भर करती है ( makeआपके उदाहरण में) सफलतापूर्वक पूरा हुआ। उदाहरण के लिए, make foo Enter> ./foo Enter एक समस्या पैदा कर सकता है। आप चीजों को टाइप करने की आदत में पड़ने की कोशिश कर सकते हैं make && make check, जैसे कि दूसरी कमांड को तभी अंजाम दिया जाएगा जब पहले वाला सफल हो जाता है।
  2. यह सैद्धांतिक रूप से संभव है कि पहला कमांड (प्रक्रिया) दूसरे कमांड का हिस्सा पढ़ सकता है, या अन्यथा इसे टर्मिनल इनपुट बफर से हटा सकता है। यदि यह पहले छह वर्णों को खा जाता है make check, तो आप कमांड को निष्पादित करना समाप्त करेंगे heck, जो संभवतः आपके सिस्टम पर मौजूद नहीं है (लेकिन कुछ बुरा हो सकता है)। यदि पहला आदेश कुछ सौम्य है जिसे आप जानते हैं और विश्वास करते हैं, तो मुझे तुरंत कोई समस्या नहीं दिखाई देती है।
  3. यह कैसे / क्यों काम करता है? सिस्टम बफ़र्स कीबोर्ड इनपुट। यह ई-मेल की तरह एक छोटा है: आप थोड़े समय में एक व्यक्ति को पांच संदेश भेज सकते हैं, और वे उसके इनबॉक्स में बैठेंगे, उन्हें पढ़ने के लिए इंतजार करेंगे। इसी तरह, जब तक पहली कमांड कीबोर्ड से नहीं पढ़ रही है, तब तक आप जो कमांड टाइप करते हैं, वे बैठेंगे और शेल के इंतजार में उन्हें पढ़ने के लिए इंतजार करेंगे। एक सीमा है कि कितना "टाइप-फॉरवर्ड" बफर किया जा सकता है, लेकिन यह आमतौर पर कई सौ अक्षर हैं (यदि कई हजार नहीं हैं)।

2
बिंदु 1 करने के लिए, कल्पना, यानी कि आदेशों से संबंधित नहीं हैं lsऔर mountउदाहरण के लिए। मैं यह समझने की कोशिश कर रहा हूं कि बफर इनपुट कैसे संभाला जाता है। जवाब के लिए धन्यवाद।
१११ ---
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.