पाइपिंग STDERR बनाम STDOUT


24

" लिनक्स: पूर्ण संदर्भ 6 वें संस्करण " (पृष्ठ 44) के अनुसार, आप पुनर्निर्देशन प्रतीकों का उपयोग करके केवल STDERR को पाइप कर सकते हैं |&

मैंने इसे जांचने के लिए एक बहुत ही सरल स्क्रिप्ट लिखी है:

#!/bin/bash
echo "Normal Text."
echo "Error Text." >&2

मैं इस स्क्रिप्ट को इस तरह चलाता हूं:

./script.sh |& sed 's:^:\t:'

संभवतया, केवल STDERR पर छपी लाइनें ही इंडेंट की जाएंगी। हालाँकि, यह वास्तव में इस तरह से काम नहीं करता है, जैसा कि मैं देख रहा हूँ:

    Normal Text.
    Error Text. 

मुझसे यहां क्या गलत हो रहा है?

जवाबों:


26

मुझे नहीं पता कि आपकी पुस्तक किस पाठ का उपयोग करती है, लेकिन बैश मैनुअल स्पष्ट है (यदि आप पहले से पुनर्निर्देशन से थोड़ा परिचित हैं):

यदि |&उपयोग किया जाता है, तो कमांड 1 की मानक त्रुटि, इसके मानक आउटपुट के अलावा, पाइप के माध्यम से कमांड 2 के मानक इनपुट से जुड़ी है; इसके लिए आशुलिपि है 2>&1 |। मानक आउटपुट में मानक त्रुटि का यह निहित पुनर्निर्देशन कमांड द्वारा निर्दिष्ट किसी भी पुनर्निर्देशन के बाद किया जाता है।

इसलिए यदि आप मानक आउटपुट और मानक त्रुटि को मिश्रित नहीं करना चाहते हैं, तो आपको मानक आउटपुट को कहीं और पुनर्निर्देशित करना होगा। देखें कि कैसे मानक त्रुटि स्ट्रीम (stderr) grep है?

{ ./script.sh 2>&1 >&3 | sed 's:^:\t:'; } 3>&1

दोनों 1 और 3 fd script.shऔर sedफिर भी मूल stdout गंतव्य को इंगित करेंगे। यदि आप एक अच्छे नागरिक बनना चाहते हैं, तो आप उन fd 3 को बंद कर सकते हैं, जिन्हें उन आज्ञाओं की आवश्यकता नहीं है:

{ ./script.sh 2>&1 >&3 3>&- | sed 's:^:\t:' 3>&-; } 3>&1

bashऔर (fd चाल) ksh93के >&3 3>&-लिए >&3-संघनन कर सकते हैं ।


बैश मैनुअल मेरे लिए पूरी तरह से स्पष्ट नहीं है। मैं काफी समझ में नहीं आता क्यों ख़ाली की तरह है ./script.sh > /tmp/stdout_goes_here |& grep 'grepping_script_stderr'काम नहीं करता, यानी इरादा के रूप में: रीडायरेक्ट script.shकी stdout(जो, मैनुअल टुकड़ा पहले होना चाहिए के अनुसार), तो अनुमति देने के grepस्क्रिप्ट के कार्रवाई करने के लिए stderr। इसके बजाय, stderrऔर tdout` दोनों का अंतstdout_goes_here
sxc731

1
@ sxc731 के |&लिए शॉर्टहैंड है 2>&1 |। तो >/tmp/stdout_goes_here |&रीडायरेक्ट करने के लिए stdout /tmp/stdout_goes_here, तो 2>&1जहाँ भी stdout जा रहा है, जो करने के लिए stderr पुनर्निर्देश /tmp/stdout_goes_here, और अंत में |किसी भी इनपुट प्राप्त नहीं होता है, क्योंकि आदेश के उत्पादन में पुनः निर्देशित किया गया है। इस बात का ध्यान रखें कि जहाँ भी फाइल डिस्क्रिप्टर 1 में जा रहा है , उसे >&1रीडायरेक्ट करें, जहाँ भी डिस्क्रिप्टर 1 फाइल करने के लिए नहीं है, वहाँ जाना समाप्त हो जाएगा । केवल stderr को पाइप करने के लिए और एक फाइल में stdout रीडायरेक्ट करें, एक तरीका है 2>&1 >/tmp/stdout_goes_here |
गाइल्स 'एसओ- बुराई को रोकना'

6

|&स्टड करने के लिए stderr पाइप, जैसे 2>&1 |, तो अगले कार्यक्रम दोनों स्टड पर मिल जाएगा।

$cat test.sh
#!/bin/bash
echo "Normal Text."
echo "Error Text." >&2
$./test.sh | sed 's:^:\t:'
Error Text.
        Normal Text.
$ ./test.sh |& sed 's:^:\t:'
        Normal Text.
        Error Text.

ओह, तो यह मूल रूप से लंबी अभिव्यक्ति के बराबर है runcommand 2>&1 | tee? यानी runcommand |& tee?
नैफुली केयू

हां, वे वही हैं।
केविन

1

|&के लिए bash सिर्फ एक (बहुत पोर्टेबल नहीं) शॉर्टकट है 2>&1 |, इसलिए आपको प्रत्येक पंक्ति को इंडेंटेड देखना चाहिए।

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