लिनक्स में पाइपिंग / रीडायरेक्शन कैसे काम करता है?


1

मेरे पास रीडायरेक्शन स्टड / स्टडआउट के ये तीन उदाहरण हैं, उनमें से केवल एक ही काम कर रहा है जिस तरह से इसका इरादा है। मुझे अच्छा लगेगा अगर कोई मुझे समझा सके।

लक्ष्य सामग्री को फ़ाइल 1 में क्रमबद्ध करना और उसी फ़ाइल में परिवर्तनों को सहेजना है।

  1. सॉर्ट file1 | tee file1> / dev / null --------> यह काम करता है

  2. सॉर्ट file1 | tee file1 --------> file1 की सामग्री मिट जाएगी

  3. सॉर्ट file1 | tee file1> file2 --------> File1 की सामग्री मिट जाएगी

पुनश्च। टीई प्रत्येक फ़ाइल के लिए मानक इनपुट की प्रतिलिपि बनाता है, और मानक आउटपुट के लिए भी।

पहला उदाहरण क्या काम करता है?


4
बस रिकॉर्ड के लिए: यदि आप उपयोग GNU sortकर रहे हैं तो आप -oविकल्प का उपयोग कर सकते हैं sort file1 -o file1:।
अर्कादियुस डेर्ब्स्की

इस जानकारी के लिए धन्यवाद, मैं यह नहीं जानता था। लेकिन मैंने सॉर्ट कमांड को एक उदाहरण के रूप में दिया, -o विकल्प अन्य कमांड जैसे कि सेड और कट के साथ नहीं आता है। तो एक फाइल की सामग्री में हेरफेर करने के लिए और उसमें परिवर्तन लिखने के लिए मुझे पाइपिंग / पुनर्निर्देशन विधियों का उपयोग करने के लिए मजबूर करना होगा, जो मुझे नहीं पता कि वे कैसे वैचारिक रूप से काम कर रहे हैं। जैसा कि आप ऊपर देख सकते हैं, मैं उस तंत्र का पता नहीं लगा सकता जिसने पहले एक को काम करने के लिए बनाया था लेकिन अन्य दो को नहीं।
user3464156

बैश और टी के लिए मैन पेज व्यापक उदाहरण प्रदान करते हैं जो आमतौर पर लागू किए गए कार्यान्वयन के लिए विशिष्ट होते हैं, और noclobber जैसी चीजों के दुष्प्रभावों के बारे में गहराई में जाएंगे .....
डॉन साइमन

जवाबों:


0

डेबियन व्हीज़ी पर मेरे परीक्षणों के अनुसार, सभी 3 परिदृश्यों में दोनों परिणाम हो सकते हैं (फ़ाइल 1 को सॉर्ट किया जाता है और वापस स्वयं लिखा जाता है या कुछ भी नहीं सॉर्ट किया जाता है और फ़ाइल 1 को कुछ भी नहीं लिखा जाता है।

मेरा मानना ​​है कि यह सामान्य व्यवहार है और लिनक्स फ़ाइलों के साथ काम करने के तरीके से आता है। कमांड के बारे में सोचें - सॉर्ट कमांड फ़ाइल 1 को पढ़ना शुरू करता है और तुरंत टी को आउटपुट करता है। टी आउटपुट को पढ़ता है, इसे file1 पर वापस लिखता है और इसे / dev / null को प्रिंट करता है। यदि पूरी फ़ाइल 1 को पढ़ने के लिए सॉर्ट करने की स्थिति में, टी को सॉर्ट किया गया आउटपुट मिलता है। लेकिन अगर मामले में यह फ़ाइल पर लॉक हो जाता है, तो यह इसे मिटा देता है (टी हमेशा आउटपुट फ़ाइल मिटाता है, सिवाय इसके जब एपेंड विकल्प का उपयोग किया जाता है) और यह आपके सभी 3 परिदृश्यों में बहुत कुछ हो रहा है।

इसे छोटा करने के लिए, कहने दें कि कभी-कभी फ़ाइल 1 पढ़ने के लिए पर्याप्त रूप से त्वरित नहीं होता है। ऐसे मामले में टी फ़ाइल को मिटा देती है इससे पहले कि वह इसे पढ़ सके।

मैं निम्नलिखित प्रक्रिया की सिफारिश करूंगा:

cat file1 | sort > /tmp/sorting.tmp; mv /tmp/sorting.tmp file1

यदि आप स्टडआउट पर सॉर्ट किए गए आउटपुट को देखना चाहते हैं, तो इसे इस तरह से करें:

cat file1 | sort | tee /tmp/sorting.tmp; mv /tmp/sorting.tmp file1

मल्टीप्रोसेसर सिस्टम पर 1 फ़ाइल के साथ 2 अलग-अलग कमांड को काम करने देना अच्छा नहीं है - आप कभी भी सुनिश्चित नहीं हो सकते हैं कि कौन पहले निष्पादित होता है। एकल पिरोया प्रणाली पर, व्यवहार अलग होगा - अनुक्रमिक।


धन्यवाद थॉमस, आपका जवाब बहुत स्पष्ट था। अब मैं समझता हूं कि मेरी समस्या सॉर्ट और टी के साथ नहीं थी, लेकिन यह लिनक्स में पाइप और पुनर्निर्देशन कैसे काम करता है, के साथ था। हालाँकि @jcoppens ने लगभग वही उत्तर दिया लेकिन आप जैसे थे वैसा विशिष्ट नहीं था।
user3464156

2

मुझे संदेह है कि वह व्यवहार अनुमानित है (और निश्चित रूप से उस पर निर्भर नहीं होगा)। teeआदेश शायद 'अन्य' गंतव्य के लिए अपने इनपुट भेजने के लिए एक नई प्रक्रिया शुरू होता है। ऑपरेटिंग सिस्टम आउटपुट को तब तक 'बफर' करेगा जब तक कि वह उस बिंदु तक नहीं पहुंच जाता जहां वह गंतव्य फ़ाइल बनाता है और फ़ाइल को अपना अस्थायी बफर लिखता है। ऐसा होने का सटीक क्षण (और स्रोत को अधिलेखित) शायद इस पर निर्भर करता है:

  • फ़ाइल का आकार और बफर के लिए उपलब्ध मेमोरी
  • बीता हुआ समय
  • यदि पाइप से teeखत्म करने के लिए इनपुट

यह इससे कहीं अधिक गहरा है bash: यह कार्यक्रम के काम करने का तरीका है जो bashशुरू होता है। शेल सिर्फ आपके द्वारा टाइप किए गए कमांड की व्याख्या करता है, और कमांड को निष्पादित करने के लिए आवश्यक प्रोग्राम शुरू करता है। शेल का कोई नियंत्रण नहीं है कि प्रत्येक प्रोग्राम कैसे काम करता है, और यहां तक ​​कि उन कार्यक्रमों को कैसे इंटरैक्ट करता है, इस पर भी कम। एक इनपुट फ़ाइल से डेटा लेने के लिए एक प्रोग्राम (या कार्यक्रमों का एक सेट) पूछना, और एक ही वाक्य में एक ही इनपुट फ़ाइल पर परिणाम लिखना, उपयोगकर्ता की जिम्मेदारी है।

यह मत भूलो कि बैश केवल उपयोगकर्ता कमांड का दुभाषिया है: यह shellउपयोगकर्ता के इरादों को सिस्टम कॉल में बदलने के लिए ऑपरेटिंग सिस्टम के आसपास है।

और यह प्रलेखित है , भी! या यह मेल , जो इसी तरह की समस्याओं को संबोधित करता है। या यह StackOverflow थ्रेड । या यह सर्वरफॉल्ट थ्रेड

ध्यान दें कि यह पुनर्निर्देशन के साथ भी हो सकता है stdin: यदि आप किसी फ़ाइल से इनपुट कमांड लेते हैं $ myprog < commandfile:। अगर myprogकमांडफाइल को लिखते हैं, तो कोई गारंटी नहीं है कि सभी commandfileकमांड निष्पादित होंगे।

वास्तव में बुनियादी सादृश्य इस अनुदेश सूची की तरह होगा:

- Execute the instructions step by step
- Dip this instruction list in a bucket of black paint
- Type in the following commands:
  find /etc -type f -exec cat '{}' \; | tr -c '.[:digit:]' '\n' \
  | grep '^[^.][^.]*\.[^.][^.]*\.[^.][^.]*\.[^.][^.]*$'

मुझे लगता है कि आप पहले एक प्रति बना लेंगे? ( एडवांस बैश-स्क्रिप्टिंग गाइड से ली गई कमांड )


ठीक है, लेकिन पहला उदाहरण हमेशा काम क्यों करता है और अन्य दो नहीं? खासकर जब पहला, सैद्धांतिक रूप से, तीसरे से मेल खाता है। ps: - सभी तीन उदाहरण एक ही फ़ाइल का उपयोग करते हैं, इसलिए आकार समान है और इसलिए बफर है।
user3464156

जांचें कि क्या यह अभी भी एक बड़ी फ़ाइल के साथ काम करता है - 64kB से अधिक या 128kB। पहले और तीसरे बहुत अलग हैं। पहला स्क्रीन आउटपुट को / dev / null में रीडायरेक्ट करता है, जो बहुत तेज़ है, जबकि तीसरा इसे एक वास्तविक फ़ाइल में भेजता है, जिसमें बहुत सारा काम होता है - ओपनिंग, बफरिंग, क्लोजिंग और अन्य प्रशासनिक कार्य - और डिस्क तक पहुंच शामिल करता है ।
jcoppens 18

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

टिप्पणी बहुत लंबी थी, मैंने इसे उत्तर में जोड़ दिया है।
jcoppens

वैसे, क्या आपने बड़ी फ़ाइलों के साथ परीक्षण किया था?
jcoppens

0

इसलिए आप चाहते हैं कि फ़ाइल की मूल सामग्री बनी रहे, जबकि फ़ाइल को परिवर्तनों के साथ जोड़ दिया जाए?

डिफ़ॉल्ट रूप से लिखता है, परिवर्तनों के साथ फ़ाइल को जोड़ने के लिए -a ध्वज का उपयोग करने का प्रयास करें।


1
असल में, मैं नहीं चाहता हूं कि मैं आगे बढ़ना चाहता हूं। यह पहले उदाहरण के साथ काम करता है। मैं पाइपिंग / पुनर्निर्देशन के पीछे के तंत्र को जानना चाहता हूं जो केवल काम करने के लिए पहला उदाहरण देता है लेकिन अन्य दो नहीं।
user3464156

सॉर्ट file1 | टी 1 फ़ाइल 1 फाइल 1 में बदलाव करता है, और उन्हें फाइल पर लिखता है। सुनिश्चित नहीं हैं कि आप क्या पूछ रहे हैं?
अजूमा

सॉर्ट file1 | tee file1
फ़ाइल

0
sort file1 | tee file1 > tmp && mv file1 original && mv tmp file1

आप फ़ाइल को एक प्लेसहोल्डर को लिख सकते हैं, मूल को बैकअप में बदल सकते हैं, फिर प्लेसहोल्डर को मूल में ले जा सकते हैं।


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