Gcc से '>' पुनर्निर्देशित त्रुटि संदेश क्यों नहीं है?


9

मैंने निम्नलिखित प्रोग्राम को new.c में संग्रहीत किया है

int main() 
{ 
    a;
    return 0; 
}

यह एक त्रुटि संदेश देता है। मैं इस संदेश को एक फ़ाइल में भेजना चाहता हूं। इसलिए मैंने निम्नलिखित कमांड का उपयोग किया

gcc new.c > temp.txt

लेकिन फिर भी मुझे टर्मिनल पर आउटपुट मिल रहा था। मैं Ubuntu 13.04 का उपयोग कर रहा हूं। मैं इसे कैसे कारगर बना सकता हूं?


जवाबों:


16

जब आप किसी प्रोग्राम को संकलित करते हैं gcc, तो विभिन्न प्रकार के आउटपुट होते हैं: टू stdoutऔर stderr। आम तौर पर, एक फ़ाइल को >डायरेक्ट stdoutस्ट्रीम करेगा (उदाहरण के लिए, एक का परिणाम printf("hello world\n");भेजा जाता है stdout)। हालाँकि, stderrइसे स्क्रीन पर भेजा जाना जारी है, क्योंकि यह माना जाता है कि "कुछ असाधारण है जिसके बारे में आपको बताया जाना चाहिए"।

एक फ़ाइल पर स्टाडर को पुनर्निर्देशित करने का एक तरीका है - आप इसे निम्न (बहुत सहज नहीं) कमांड के साथ करते हैं:

gcc new.c &> myFile

&>"सब कुछ पुनर्निर्देशित करें" के लिए "बैश शॉर्टहैंड" कहां है। जैसा कि @CharlesDuffy द्वारा बताया गया था, पोसिक्स कंप्लेंट फॉर्म है

gcc new.c > myFile 2>&1

इस का अर्थ है "संकलन 'new.c' और भेजें stdoutकरने के लिए myFile। और भेजने stderrके रूप में एक ही जगह (2) stdout( &1stdout के रूप में एक ही स्थान पर" =) "।

आप http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-3.html और http://mywiki.wooledge.org/BashFAQ/055 पर विभिन्न रीडायरेक्ट पर अधिक विवरण पाएंगे।

वैसे, यदि आप अपने कार्यक्रम के भीतर से कुछ विशेष रूप से भेजना चाहते हैं, तो आप stderrनिम्न के साथ ऐसा कर सकते हैं

fprintf(stderr, "hello world - this is urgent.\n");

यदि आप इसे किसी प्रोग्राम में शामिल करते हैं, तो प्रोग्राम को चलाएं और "नॉर्मल" आउटपुट को फाइल में भेजें, यह कंसोल पर दिखाई देगा। इसलिए यदि आप उपरोक्त को निष्पादन योग्य में संकलित करते हैं urgent, तो टाइप करें

./urgent > /dev/null

कंसोल पर, आपका आउटपुट स्क्रीन पर दिखाई देगा।


2
mywiki.wooledge.org/BashFAQ/055 शायद पुनर्निर्देशन का बेहतर परिचय है। इसके अलावा, एक को वास्तव में पोसिक्स-कंप्लेंट फॉर्म ( >myFile 2>&1) के साथ-साथ बैश एक्सटेंशन ( &>) भी शुरू करना चाहिए ।
चार्ल्स डफी

@CharlesDuffy - दोनों बहुत अच्छे अंक। मैं उन्हें पूर्णता के लिए अपने उत्तर में शामिल करूंगा।
फ्लोरिस

11

क्योंकि >पुनर्निर्देश केवल स्टडआउट करते हैं, और त्रुटियों को लिखा जाता है stderr, आपको इसके बजाय निम्नलिखित में से एक का उपयोग करने की आवश्यकता है:

gcc new.c &> temp.txt ## redirect both stdout and stderr using bash or zsh only

... या ...

gcc new.c >temp.txt 2>&1 ## redirect both stdout and stderr in any POSIX shell

&>एक BASH एक्सटेंशन है जो दोनों को stdoutऔर stderrएक फाइल पर रीडायरेक्ट करता है ; अन्यथा, सबसे आसान तरीका है पहले रीडायरेक्ट ( >temp.txt) को रीडायरेक्ट करना , और उसके बाद stderr (FD 2) को पहले से रीडायरेक्ट फ़ाइल हैंडल की एक कॉपी बना देना, जैसे: (FD 1) 2>&1


4

जैसा कि दूसरों ने कहा है, linux दो अलग-अलग आउटपुट स्ट्रीम प्रदान करता है:

स्टडआउट , या "मानक आउटपुट" वह जगह है जहां सभी नियमित आउटपुट जाते हैं।
              आप इसे फ़ाइल डिस्क्रिप्टर का उपयोग करके संदर्भित कर सकते हैं 1

stderr , या "मानक त्रुटि" आउट-ऑफ-बैंड जानकारी के लिए एक अलग स्ट्रीम है।
              आप इसे फ़ाइल डिस्क्रिप्टर का उपयोग करके संदर्भित कर सकते हैं 2

दो अलग-अलग आउटपुट स्ट्रीम क्यों? काल्पनिक आदेशों की एक पाइपलाइन पर विचार करें:

 decrypt $MY_FILE | grep "secret" | sort > secrets.txt

अब कल्पना करें कि decryptकमांड विफल रहता है और एक त्रुटि संदेश उत्पन्न करता है। यदि यह उस संदेश को भेजता है stdout, तो यह पाइप में भेज देगा, और जब तक कि यह "गुप्त" शब्द नहीं था, तब तक आप इसे कभी नहीं देखेंगे। तो आप एक खाली आउटपुट फ़ाइल के साथ समाप्त हो जाएंगे, बिना किसी विचार के।

हालांकि, चूंकि पाइप केवल कब्जा करता है stdout, decryptकमांड अपनी त्रुटियों को भेज सकता है stderr, जहां वे कंसोल पर प्रदर्शित होंगे।

आप अनुप्रेषित कर सकते हैं stdoutऔर stderr, या तो एक साथ या स्वतंत्र:

# Send errors to "errors.txt" and output to "secrets.txt"
# The following two lines are equivalent, as ">" means "1>"
decrypt $MY_FILE 2> errors.txt > secrets.txt
decrypt $MY_FILE 2> errors.txt 1> secrets.txt

आप त्रुटियों को पुनर्निर्देशित कर सकते हैं stdoutऔर उन्हें संसाधित कर सकते हैं जैसे कि वे सामान्य आउटपुट थे:

# The operation "2>&1" means "redirect file descriptor 2 to file
# descriptor 1. So this sends all output from stderr to stdout.
# Note that the order of redirection is important.
decrypt $MY_FILE > errors.txt 2>&1 

# This may be confusing.  It will store the normal output in a file
# and send error messages to stdout, where they'll be captured by 
# the pipe and then sorted.
decrypt $MY_FILE 2>&1 > output.txt | sort

आप एक "शॉर्टहैंड" नोटेशन का उपयोग एक ही फाइल पर stdout और stderr दोनों को पुनर्निर्देशित करने के लिए कर सकते हैं:

decrypt $MY_FILE &> output.txt

और, आखिरकार, >ऑपरेटर इसे लिखने से पहले अपनी आउटपुट फ़ाइल को पहले काट देगा। यदि, इसके बजाय, आप किसी मौजूदा फ़ाइल में डेटा जोड़ना चाहते हैं , तो >>ऑपरेटर का उपयोग करें :

decrypt $MY_FILE 2>> more_errors.txt >> more_secrets.txt
decrypt $MY_FILE >> more_output.txt 2>&1

1
दो क्विबर्ल्स: (1) अयोग्य पैरामीटर विस्तार ( $FOO) का उपयोग बग्स का एक सामान्य स्रोत है, और उदाहरणों में इसका प्रदर्शन करना इतना महान नहीं है। (२) ऑल-अपरकेस वैरिएबल नामों का उपयोग पर्यावरण और बिल्ट-इन वैरिएबल्स (कन्वेंशन द्वारा अपरकेस) और लोकल वैरिएबल्स (कन्वेंशन द्वारा लोअरकेस) के बीच होने वाले नेमस्पेस संघर्ष का प्राथमिक कारण है। (३) लोगों को बार-बार इस्तेमाल करने के लिए प्रोत्साहित करना >>(जो एक कमांड में इस्तेमाल होने पर हर बार फाइल को फिर से खोलता है) एक बार फाइल खोलने के बजाय और कई कमांड द्वारा उपयोग के लिए फाइल डिस्क्रिप्टर को खुला छोड़ देने से परिणाम अक्षम हो जाते हैं।
चार्ल्स डफी

... आखिरी बिंदु पर, तुलना करें: exec 4>secrets; echo "this is a secret" >&4; echo "this is another secret" >&4
चार्ल्स डफी

+1 मुझे ईमानदार रखने के लिए धन्यवाद, @CharlesDuffy। सभी अच्छे अंक। मैं जानबूझकर execसादगी के लिए छोड़ दिया गया था , हालांकि व्यवहार में यह आमतौर पर एक बेहतर रणनीति है।

इसके अलावा, के ढह किया जा सकता है या (जहां रिक्त स्थान पहले और बाद में वहाँ होना चाहिए एक है, और इससे पहले कि )। command₁ > output_file ; command₂ >> the_same_output_file( command₁ ; command₂ )  > output_file{ command₁ ; command₂ ;  }  > output_file{;}
जी-मैन का कहना है कि 'मोनिका' को
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.