`कमांड 1> फाइल.टेक्स्ट 2> फाइल.टेक्स्ट का व्यवहार` कमांड 1> फाइल.नेट 2> और 1` से भिन्न क्यों है?


20

जब आप एक ही फ़ाइल में stdout और stderr दोनों को पुनर्निर्देशित करना चाहते हैं, तो आप इसका उपयोग करके command 1>file.txt 2>&1, या कर सकते हैं command &>file.txt। लेकिन command 1>file.txt 2>file.txtउपरोक्त दो आदेशों से अलग व्यवहार क्यों है ?

निम्नलिखित एक सत्यापन आदेश है।

$ cat redirect.sh
#!/bin/bash

{ echo -e "output\noutput" && echo -e "error" 1>&2; } 1>file.txt 2>&1
{ echo -e "output\noutput" && echo -e "error" 1>&2; } 1>file1.txt 2>file1.txt
{ echo -e "error" 1>&2 && echo -e "output\noutput"; } 1>file2.txt 2>file2.txt
{ echo -e "output" && echo -e "error\nerror" 1>&2; } 1>file3.txt 2>file3.txt
{ echo -e "error\nerror" 1>&2 && echo -e "output"; } 1>file4.txt 2>file4.txt

$ ./redirect.sh

$ echo "---file.txt---"; cat file.txt;\
echo "---file1.txt---"; cat file1.txt; \
echo "---file2.txt---"; cat file2.txt; \
echo "---file3.txt---"; cat file3.txt; \
echo "---file4.txt----"; cat file4.txt;
 ---file.txt---
output
output
error
---file1.txt---
error

output
---file2.txt---
output
output
---file3.txt---
error
error
---file4.txt----
output
rror

जहां तक ​​परिणामों को देखा जाता है, ऐसा लगता है कि जब आप दौड़ते हैं तो दूसरी प्रतिध्वनि पहली प्रतिध्वनि स्ट्रिंग को अधिलेखित कर देती है command 1>file.txt 2>file.txt, लेकिन मुझे नहीं पता कि यह क्यों होगा। (कहीं एक संदर्भ है?)

जवाबों:


43

आपको दो बातें जानने की जरूरत है:

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

    इस तरह के बदलाव बुला प्रक्रियाओं के द्वारा बनाए जाते हैं read()/ readv(), write()/ writev(), lseek(), और उस तरह का सिस्टम कॉल। echoआदेश कॉल write()/ writev()निश्चित रूप से।

तो क्या होता है:

  • command 1>file.txt 2>&1केवल एक फ़ाइल विवरण बनाता है, क्योंकि शेल केवल एक बार एक फ़ाइल खोलता है। खोल बनाता है दोनों मानक आउटपुट और मानक त्रुटि फ़ाइल वर्णनकर्ता कि एकल फाइल वर्णन करने के लिए नक्शे। यह मानक त्रुटि पर मानक आउटपुट को डुप्लिकेट करता है । तो या तो फाइल डिस्क्रिप्टर के माध्यम से एक लिखित साझा की गई वर्तमान फ़ाइल स्थिति को स्थानांतरित कर दिया जाएगा: प्रत्येक लेखन पिछले फ़ाइल के आम फ़ाइल विवरण लिखने के बाद जाता है। और जैसा कि आप देख सकते हैं echoआदेशों के परिणाम एक दूसरे को अधिलेखित नहीं करते हैं।
  • command 1>file.txt 2>file.txtदो फ़ाइल विवरण बनाता है , क्योंकि शेल दो स्पष्ट रीडायरेक्ट के जवाब में एक ही फ़ाइल को दो बार खोलता है। मानक आउटपुट और मानक त्रुटि फ़ाइल डिस्क्रिप्टर दो अलग-अलग फ़ाइल विवरणों के लिए मैप करते हैं, जो तब एक ही फ़ाइल में मैप को बदल देते हैं। दो फ़ाइल विवरणों में पूरी तरह से स्वतंत्र वर्तमान फ़ाइल स्थिति होती है, और प्रत्येक लेखन उसी फ़ाइल विवरण पर पिछले लेखन को तुरंत चला जाता है। और जैसा कि आप देख सकते हैं कि परिणाम यह है कि जो एक के माध्यम से लिखा जाता है वह दूसरे के माध्यम से लिखी गई चीज़ों को अलग-अलग लिख सकता है, जिस तरह से आप लेखन को निष्पादित करते हैं उसी के अनुसार।

आगे की पढाई


1
होना चाहिए खुले फ़ाइल वर्णन के बजाय फ़ाइल विवरण । यह रिकॉर्ड के बारे में अधिक है कि फ़ाइल को फ़ाइल से अधिक कैसे खोला गया था। कि POSIX, Linux, Solaris और GNU प्रलेखन द्वारा प्रयुक्त शब्दावली कम से कम है।
स्टीफन चेज़लस

16

इसका उपयोग करना >फ़ाइल को अधिलेखित करने के लिए कहता है। चूँकि आपके पास दो अलग-अलग ऑपरेशनों में फाइल करने के लिए स्टडआउट और स्टडरर लेखन है, इसलिए लिखने वाला आखिरी ओवर पहले लिख देगा।

तुम कर सकते हो:

command 1>>file.txt 2>>file.txt

या

command &>file.txt केवल बैश v4 और ऊपर।

>> इसे फ़ाइल को जोड़ने के लिए कहता है ताकि यह पिछले ऑपरेशन के आउटपुट को प्रतिस्थापित न करे।

&> लिखने का एक आसान तरीका है 2>&1


2
क्यों ls 1>&0और ls 0>&0अभी भी ls के उत्पादन को दिखाता है?
यवैन

मुझे आश्चर्य है कि >>काम करता है का उपयोग कर । इसमें स्वतंत्र ऑफसेट के साथ दो फ़ाइल विवरणों की समस्या क्यों नहीं है? @ जेडेबीपी, क्या आप जानते हैं? मैंने सोचा था कि एपेंड मोड में एक फाइल खोलना राइट मोड में खुलने के बराबर था, अंतिम स्थिति की मांग करना, फिर आगे की मांग को अस्वीकार करना।
जोएल सेप

4
@jlmg: अपेंड-मोड फाइलें खोजी जा सकती हैं, लेकिन हर लेखन एक अंत की तलाश के साथ पूर्वनिर्मित होता है। क्या वह निहित तलाश परमाणु है मेरे लिए कम स्पष्ट है।
केविन

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

1
@ केविन पूरी तरह से POSIX- कम्प्लायंट फाइल सिस्टम पर, निहित O_APPEND की तलाश परमाणु है। कहा कि, हर फाइलसिस्टम प्रासंगिक शब्दार्थ को ठीक से लागू नहीं करता है - उदाहरण के लिए, एनएफएस (कम से कम v3 और पूर्व - मैं v4 पर स्पष्ट नहीं हूं) के पास वायर प्रोटोकॉल में बेक किया गया प्रासंगिक समर्थन नहीं है, इसलिए सर्वर में है यह जानने का कोई तरीका नहीं है कि क्या क्लाइंट ने किसी फ़ाइल को खोला है O_APPEND
चार्ल्स डफी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.