सवाल `>` के बराबर `>` के साथ पुनर्निर्देशन है जब लक्ष्य फ़ाइल अभी तक मौजूद नहीं है?


बैश या शेल जैसे शैल पर विचार करें। के बीच बुनियादी अंतर > तथा >> लक्ष्य फ़ाइल मौजूद होने पर खुद को एक मामले में प्रकट करता है:

  • > फ़ाइल को शून्य आकार में छोटा कर देता है, फिर लिखता है;
  • >> छंटनी नहीं करता है, यह फ़ाइल के अंत में लिखता है (संलग्न करता है)।

अगर फ़ाइल मौजूद नहीं है तो यह शून्य आकार के साथ बनाई गई है; फिर लिखा है। यह दोनों ऑपरेटरों के लिए सच है। ऐसा प्रतीत होता है कि ऑपरेटर बराबर हैं जब लक्ष्य फ़ाइल अभी तक मौजूद नहीं है।

क्या वे वास्तव में हैं?


79
2017-07-23 08:42


मूल




जवाब:


tl; डॉ

नहीं। >> अनिवार्य रूप से "हमेशा फाइल का अंत करना चाहते हैं" जबकि > अंतिम लिखित स्थान पर एक सूचक को बनाए रखता है।


पूरा जवाब

(नोट: डेबियन जीएनयू / लिनक्स 9 पर किए गए मेरे सभी परीक्षण)।

एक और अंतर

नहीं, वे बराबर नहीं हैं। वहाँ है एक और अंतर। यह स्वयं को प्रकट कर सकता है कि लक्ष्य फ़ाइल पहले या नहीं थी या नहीं।

इसे देखने के लिए, एक प्रक्रिया चलाएं जो डेटा उत्पन्न करती है और फ़ाइल के साथ रीडायरेक्ट करती है > या >> (उदाहरण के लिए pv -L 10k /dev/urandom > blob)। इसे फ़ाइल के आकार को चलाने और बदलने दें (उदा truncate)। आप इसे देखेंगे > जबकि (बढ़ते) ऑफ़सेट रहते हैं >> हमेशा अंत में संलग्न होता है।

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

एक और उदाहरण संलग्न करना है (एक अलग के साथ >>) डेटा उत्पन्न करने की प्रक्रिया चल रही है और फ़ाइल को लिखते समय कुछ अतिरिक्त है। यह फ़ाइल को बढ़ाने के समान है।

  • के साथ उत्पन्न प्रक्रिया > इसके वांछित ऑफसेट पर लिखेंगे और अंततः अतिरिक्त डेटा ओवरराइट करेंगे।
  • के साथ उत्पन्न प्रक्रिया >> नया डेटा छोड़ देगा और इसे अतीत में जोड़ देगा (दौड़ की स्थिति हो सकती है, दो धाराएं इंटरलीव हो सकती हैं, फिर भी कोई डेटा ओवरराइट नहीं किया जाना चाहिए)।

उदाहरण

क्या यह अभ्यास में मायने रखता है? वहाँ है यह प्रश्न:

मैं एक ऐसी प्रक्रिया चला रहा हूं जो stdout पर बहुत अधिक उत्पादन उत्पन्न करता है। इसे सभी को एक फाइल में भेजना [...] क्या मैं किसी प्रकार के लॉग रोटेशन प्रोग्राम का उपयोग कर सकता हूं?

यह जवाब कहते हैं समाधान है logrotate साथ में copytruncate विकल्प जो इस तरह कार्य करता है:

पुरानी लॉग फ़ाइल को स्थानांतरित करने और वैकल्पिक रूप से एक नया निर्माण करने के बजाय प्रतिलिपि बनाने के बाद मूल लॉग फ़ाइल को स्थानांतरित करें।

मैंने जो लिखा है उसके अनुसार, पुनर्निर्देशन के अनुसार > किसी भी समय छोटा कटा हुआ लॉग बना देगा। चतुरता दिन को बचाएगी, कोई महत्वपूर्ण डिस्क स्थान बर्बाद नहीं किया जाना चाहिए। फिर भी प्रत्येक लगातार लॉग में अधिक से अधिक अग्रणी शून्य होंगे जो पूरी तरह से अनावश्यक हैं।

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

इस मामले में उपयोग कर रहे हैं >> के बजाय > काफी बेहतर है, भले ही लक्ष्य फ़ाइल अभी तक बनाई जा रही है।


प्रदर्शन

जैसा कि हम देख सकते हैं, दो ऑपरेटर न केवल तब शुरू होते हैं जब वे शुरू होते हैं लेकिन बाद में भी। इससे कुछ (सूक्ष्म?) प्रदर्शन अंतर हो सकता है। अभी के लिए मेरे पास इसका समर्थन करने या अस्वीकार करने के लिए कोई सार्थक परीक्षा परिणाम नहीं हैं, लेकिन मुझे लगता है कि आपको स्वचालित रूप से अपना प्रदर्शन सामान्य रूप से सामान्य नहीं होना चाहिए।


107
2017-07-23 08:42



इसलिए >> अनिवार्य रूप से "हमेशा फाइल का अंत करना चाहते हैं" जबकि > अंतिम लिखित स्थान पर एक सूचक को बनाए रखता है। ऐसा लगता है कि जिस तरह से वे काम करते हैं, उनमें कुछ सूक्ष्म प्रदर्शन अंतर भी हो सकता है ... - Mokubai♦
सिस्टम कॉल स्तर पर, >> का उपयोग करता है O_APPEND झंडा open()। और वास्तव में, > का उपयोग करता है O_TRUNC, जबकि >> ऐसा नहीं करता। का संयोजन O_TRUNC | O_APPEND यह भी संभव होगा, शैल भाषा सिर्फ उस सुविधा को प्रदान नहीं करती है। - ilkkachu
@jjmontes, मानक स्रोत POSIX होगा: pubs.opengroup.org/onlinepubs/9699919799.2018edition/utilities/... लेकिन निश्चित रूप से बैश के मैनुअल में रीडायरेक्शन ऑपरेटरों पर भी विवरण हैं, जिनमें गैर मानक वाले समर्थन शामिल हैं: gnu.org/software/bash/manual/html_node/Redirections.html - ilkkachu
@ilkkachu मुझे यह ब्याज के रूप में मिला, क्योंकि यह O_APPEND के बारे में विवरण बताता है जो मैं आपकी टिप्पणी के बाद सोच रहा था :): stackoverflow.com/questions/1154446/... - jjmontes
@ मोकुबाई, किसी भी सीन ओएस के पास खुली होने पर फ़ाइल की लंबाई होगी, और ध्वज की जांच करनी होगी और ऑफ़सेट को अंत में ले जाना चाहिए अन्य सभी बहीखाता में गायब होना चाहिए। अनुकरण करने की कोशिश कर रहा है O_APPEND एक साथ lseek() प्रत्येक से पहले write() हालांकि अलग होगा, अतिरिक्त सिस्टम कॉल ओवरहेड होगा। (और निश्चित रूप से यह काम नहीं करेगा, क्योंकि एक और प्रक्रिया हो सकती है write() के बीच में।) - ilkkachu