क्या फाइल डिस्क्रिप्टर कॉपियों के बिना एक ही फाइल पर stdout और stderr को पुनर्निर्देशित करना सुरक्षित है?


27

मैं खाली निर्देशिका में शुरू करता हूं।

$ touch aFile
$ ls
aFile

फिर मैं lsदो तर्क देता हूं , जिनमें से एक इस निर्देशिका में नहीं है। मैं दोनों आउटपुट स्ट्रीम नाम की फाइल पर रीडायरेक्ट करता हूं output। मैं >>एक साथ लिखने से बचने के लिए उपयोग करता हूं ।

$ ls aFile not_exist >>output 2>>output
$ cat output
ls: cannot access 'not_exist': No such file or directory
aFile

जो काम करने लगता है। क्या इस दृष्टिकोण के लिए कोई खतरे हैं?


6
वह तेजी से डाउन वोट था। पाँच सेकंड ऐसे लगे। क्या आप मुझे बता सकते हैं कि आप मेरे प्रश्न की योग्यता का आकलन इतनी जल्दी कैसे कर सकते हैं? और बेहतर अभी तक, इसमें क्या गलत है ताकि मैं इसे सुधार सकूं?
निकलें_स्टैटस

आप ls aFile not_exist &>>outputयहां अधिक मानक का उपयोग क्यों नहीं करते हैं? (ध्यान दें, मैं मान रहा हूं कि आप बैश का उपयोग कर रहे हैं ।)
फेडोनकादिफ़ेली

5
क्योंकि इससे मुझे यह समझने में मदद नहीं मिलती कि मैं किस बारे में पूछ रहा हूं। मुझे पता है कि इन धाराओं को एक ही फ़ाइल में कैसे पुनः निर्देशित किया जाए, यहां तक ​​कि आंशिक रूप से भी। अगर मैं यह जानना चाहता हूं कि प्रश्न में जो कुछ भी सुझाया गया है, उसमें कुछ गड़बड़ है या नहीं। @FedonKadifeli
exit_status

1
@FedonKadifeli &>>मानक नहीं है। यह एक अलग, अस्पष्ट वाक्यविन्यास है जो अलग-अलग गोले में अलग-अलग तरीके से काम करता है। मुझे आश्चर्य है कि आप लोग अपना सामान कहाँ से प्राप्त करते हैं।
चाचा बिली

4
बैश एक मानक नहीं है । POSIX मानक जनादेश है कि ls &>>foo ...दो comands ls &और के रूप में पार्स किया जाना चाहिए >>foo ..., और इस तरह /bin/shसे Ubuntu से अन्य गोले इसे पार्स कर रहे हैं। इसे पदावनत करने के लिए, आप यहाँ देख सकते हैं - हालाँकि मैं यह दिखावा नहीं करता कि किसी भी प्रकार का अधिकार है। आप रखवाले से पूछ सकते हैं कि bashक्या वे उस अच्छे विचार का उपयोग कर रहे हैं, हालांकि।
चाचा बिली

जवाबों:


22

नहीं, यह मानक की तरह सुरक्षित नहीं है >>bar 2>&1

जब आप लिख रहे हैं

foo >>bar 2>>bar

आप barफ़ाइल को दो बार खोल रहे हैं O_APPEND, दो पूरी तरह से स्वतंत्र फ़ाइल ऑब्जेक्ट्स बना रहे हैं [1], प्रत्येक की अपनी स्थिति (पॉइंटर, ओपन मोड आदि)।

यह बहुत विपरीत है, 2>&1जो सिर्फ dup(2)सिस्टम कॉल को कॉल कर रहा है, और उसी फ़ाइल ऑब्जेक्ट के लिए stderr और stdout विनिमेय उपनाम बनाता है।

अब, इसके साथ एक समस्या है:

O_APPENDयदि एक से अधिक प्रक्रिया एक बार में किसी फ़ाइल में डेटा जोड़ देती है, तो NFS फाइल सिस्टम पर दूषित फाइलें हो सकती हैं। ऐसा इसलिए है क्योंकि एनएफएस किसी फ़ाइल को जोड़ने का समर्थन नहीं करता है, इसलिए क्लाइंट कर्नेल को इसका अनुकरण करना होगा, जो बिना किसी दौड़ शर्त के नहीं किया जा सकता है।

आप आम तौर पर की तरह फ़ाइल की संभावना पर भरोसा कर सकते barमें foo >>bar 2>&1दो अलग-अलग काफी कम किया जा रहा स्थानों से एक ही समय में करने के लिए लिखा जा रहा। लेकिन आपके द्वारा >>bar 2>>barआपने इसे बिना किसी कारण के परिमाण के एक दर्जन आदेशों से बढ़ा दिया।

[१] पोसिक्स लिंगो में "फ़ाइल विवरण खोलें"।


3
औपचारिक रूप से, एपेंड-मोड फ़ाइलों के लिए, यह सुरक्षित है । उद्धृत मुद्दा एनएफएस में एक बग है जो इसे फाइल सिस्टम के रूप में अनुपयुक्त (गैर-पॉसिक्स-अनुरूप) बनाता है। गैर-परिशिष्ट-मोड मामले के लिए, हालांकि, यह कभी भी सुरक्षित नहीं है।
आर ..

1
वह सारहीन है। ओपी का डबल-अपेंडेड उपयोग करने के लिए सुरक्षित नहीं है (पूरी तरह से व्यर्थ होने के अलावा)। और O_APPENDवैसे भी एक बॉट की तरह है - सही ढंग से लागू करने के लिए बहुत बढ़िया।
mosvy

मेरा मानना ​​है कि एनएफएस की दौड़ की स्थिति केवल विभिन्न ग्राहकों के बीच है। क्लाइंट ओएस को अपनी प्रक्रियाओं के बीच सभी लिखने का समन्वय करना चाहिए।
बरमार

@ बरमार वह सच होगा यदि क्लाइंट ओएस केवल एक एनएफ़एस फ़ाइल के अपने दृष्टिकोण के बारे में परवाह करता है। लेकिन जब एनएफएस फाइल के साथ लिखा जाता है O_APPEND, तो क्लाइंट पहले सर्वर से फ़ाइल के "वास्तविक" आकार को पुनः प्राप्त करेगा (इनकोड को "अमान्य" करेगा) और फिर सीक + इनकोड अपडेट + लिखना और केवल अंतिम भाग करना चाहता है। ताले के तहत किया जाता है, जिसका अर्थ है कि पहला भाग अभी भी सर्वर से एक बासी आकार प्राप्त कर सकता है और स्थानीय / कैश्ड इनोड से सही को ओवरराइड कर सकता है। के साथ भी यही समस्या है lseek(SEEK_END)
मच्छी

मैं अभी भी नहीं देखता कि कैसे एक ही क्लाइंट पर दो धाराओं के बीच दौड़ की स्थिति पैदा हो सकती है। दोनों धाराओं को एक ही स्थानीय कैश्ड इनकोड को संदर्भित करना चाहिए।
बरमार

22

जब आप करते हैं तो क्या होता है

some_command >>file 2>>file

यह है कि fileदो बार आवेदन करने के लिए खोला जाएगा। यह एक POSIX फाइल सिस्टम पर करना सुरक्षित है। कोई भी लेखन जो फ़ाइल के लिए तब होता है जब इसे एपेंडिंग के लिए खोला जाता है, फ़ाइल के अंत में होगा, चाहे डेटा मानक आउटपुट स्ट्रीम या मानक त्रुटि स्ट्रीम पर आता हो।

यह परमाणु परिशिष्ट के लिए समर्थन पर निर्भर करता है अंतर्निहित फाइल सिस्टम में ऑपरेशन लिखते हैं। कुछ फाइल सिस्टम, जैसे कि एनएफएस, परमाणु परिशिष्ट का समर्थन नहीं करता है। उदाहरण के लिए देखें StackOverflow पर "फ़ाइल UNIX में परमाणु परिशिष्ट है?"

का उपयोग करते हुए

some_command >>file 2>&1

हालांकि NFS पर भी काम करेगा।

हालांकि, का उपयोग कर

some_command >file 2>file

सुरक्षित नहीं है, क्योंकि शेल आउटपुट फाइल (दो बार) को छोटा कर देगा और किसी भी स्ट्रीम पर होने वाले किसी भी लेखन को दूसरी स्ट्रीम द्वारा पहले से लिखे गए डेटा को ओवरराइट कर देगा

उदाहरण:

$ { echo hello; echo abc >&2; } >file 2>file
$ cat file
abc
o

helloस्ट्रिंग (एक समाप्त न्यू लाइन के साथ) पहले लिखा है, और फिर स्ट्रिंग abcएक नई पंक्ति के बाद मानक त्रुटि से लिखा है, अधिलेखित hell। परिणाम abcएक नई लाइन के साथ स्ट्रिंग है , उसके बाद जो पहली echoआउटपुट, एक oऔर एक नई पंक्ति से बचा है ।

echoघाव के चारों ओर दो स्वैपिंग केवल helloआउटपुट फाइल में उत्पन्न होती है क्योंकि स्ट्रिंग अंतिम लिखी जाती है और abcस्ट्रिंग से अधिक लंबी होती है । जिस क्रम में पुनर्निर्देश होता है, वह मायने नहीं रखता।

अधिक मुहावरेदार का उपयोग करना बेहतर और सुरक्षित होगा

some_command >file 2>&1

1
हालांकि यह आधुनिक गोले का सच है, जो बॉर्न या थॉमसन शेल (जहां से >>आता है) में ऐसा नहीं था, जहां >>लिखने के लिए खुल जाएगा और अंत की तलाश होगी (मुझे लगता है क्योंकि O_APPEND का अभी तक आविष्कार नहीं हुआ था)। सोलारिस 10 पर भी, /bin/sh -c '(echo a; echo b >&2) >> file 2>> file; cat file'आउटपुट b
स्टीफन चेज़लस

@ StéphaneChazelas है कि Solaris 10 के कार्यान्वयन के shसाथ या उसके फाइल सिस्टम के साथ एक मुद्दा है ?
Kusalananda

1
जो >>मूल रूप से कर रहा था, वह O_APPEND के साथ नहीं खुल रहा था, वह बिना खोले और अंत तक मांग रहा था। यह उतना मुद्दा नहीं है, यह वही है जो यह कर रहा था और इसे करने के लिए प्रलेखित किया गया था।
स्टीफन चेज़ेलस

0

यह निर्भर करता है कि आप क्या हासिल करना चाहते हैं। यह तय करना आपके लिए है कि आउटपुट के समान फ़ाइल में त्रुटियाँ होना ठीक है। यह केवल शेल की कार्यक्षमता के साथ एक फ़ाइल में पाठ को सहेज रहा है जो आपको इच्छानुसार पुनर्निर्देशित करता है। कोई निरपेक्ष हाँ या नहीं है। लिनक्स में सब कुछ कई मायनों में किया जा सकता है, यह मेरा तरीका ls notExistingFile existingFile >> output 2>&1 है सवाल का जवाब देने के लिए: खुद को पुनर्निर्देशित करने के संदर्भ में, हाँ यह पूरी तरह से सुरक्षित है।


यहाँ जो आप कह रहे हैं, उससे कहीं अधिक है। इसके >बजाय एक ही अभ्यास >>कुछ पात्रों को अधिलेखित कर देगा। तो ऐसा नहीं है कि शेल मुझे पुनर्निर्देशित करने की अनुमति देता है, क्योंकि जब मैं पुनर्निर्देशित करता हूं >, तो परिणाम अलग होता है। तो वहाँ के साथ बारीकियों हैं >, वहाँ किसी के साथ कर रहे हैं >>?
निकलें_स्टैटस

हां यह अलग होगा। जैसा कि मैंने कहा कि यह आपके लक्ष्य पर निर्भर करता है >- अधिलेखित। >>- परिशिष्ट
एंजेल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.