किसी फ़ाइल में stdout और stderr को रीडायरेक्ट कैसे करें और कंसोल को stderr प्रदर्शित करें?


18

मुझे पता है कि किसी फ़ाइल को कैसे रीडायरेक्ट करना है, और टी का उपयोग करना है; एक बुनियादी स्तर पर। इसलिए

$ alias outanderr='bash -c "echo stdout >&1; echo stderr >&2"'
# A fake "application" displaying both output and error messages.

$ outanderr 1>file      # redirect stdout to a file, display stderr
stderr

$ outanderr 2>file      # redirect stderr to a file, display stdout
stdout

$ outanderr 1>file 2>&1 # redirect both to a file, display nothing

$ outanderr | tee file; echo "-- file contents --" && cat file
# redirect stdout to a file, display both (note: order is messed up)
stderr
stdout
-- file contents --
stdout

$ outanderr 2>&1 | tee file; echo "-- file contents --" && cat file
# redirect both to a file, display both
stdout
stderr
-- file contents --
stdout
stderr

सवाल यह है कि नीचे दिए गए आउटपुट को प्राप्त करने के लिए प्रश्नपत्र के स्थान पर क्या लिखना है:

$ outanderr ???; echo "-- file contents --" && cat file
# redirect both to a file, display stderr
stderr
-- file contents --
stdout
stderr

Constaints:

  • मानकर बैश करना।
  • आदेश को फ़ाइल में रखा जाना चाहिए।
  • stderr सामग्री लाइन द्वारा वास्तविक समय लाइन में प्रदर्शित की जाती है, अर्थात कोई बफरिंग नहीं।
  • अलग स्क्रिप्ट फ़ाइलों का उपयोग किया जा सकता है।
  • जादू जरूरी हो सकता है।

outanderrआपके पास कार्यक्रम का कितना नियंत्रण है?
केविन

1
@ केविन मुझे लगता है कि प्रश्न इससे अधिक सामान्य है। यहाँ, outanderrबस एक उर्फ ​​है जो stdout करने के लिए एक लाइन प्रिंट करता है और दूसरा stderr को। विचार (यदि यह संभव है) एक सामान्य समाधान का निर्माण करना है जो किसी भी कार्यक्रम के साथ काम कर सकता है, उन्हें संशोधित किए बिना।
लैगोरेट

@lgeorget मैं समझता हूं कि, लेकिन मुझे विश्वास नहीं है कि एक सामान्य समाधान में सभी बाधाओं को कड़ाई से पूरा करना संभव है, इसलिए मैं देख रहा था कि क्या हम एक विशिष्ट प्राप्त कर सकते हैं।
केविन

@Igeorget सही है।
ट्वीस्ट्रोब

जवाबों:


12
2>&1 >>outputfile | tee --append outputfile

आसान परीक्षण के लिए:

echo -n >outputfile; bash -c "echo stdout >&1; echo stderr >&2" 2>&1 >>outputfile |
  tee --append outputfile; echo "outputfile:"; cat outputfile

1 संपादित करें:

यह फ़ाइल में stdout (केवल) लिखकर, sterr stdout बनाकर काम करता है ताकि वह पाइप से गुजरे, और उसी फाइल पर अपना आउटपुट लिख सके।

दोनों लिखते हैं कि एपेंड मोड में होना चाहिए ( >>इसके बजाय >) अन्यथा दोनों एक-दूसरे के आउटपुट को ओवरराइट कर देंगे।

चूंकि पाइप एक बफर है, इसलिए कोई गारंटी नहीं है कि आउटपुट सही क्रम में फ़ाइल में दिखाई देता है। यदि एप्लिकेशन किसी फाइल डिस्क्रिप्टर (दो पाइप) से जुड़ा होता तो यह भी नहीं बदलता। गारंटीकृत आदेश के लिए दोनों आउटपुट को एक ही चैनल से गुजरना होगा और क्रमशः चिह्नित किया जाएगा। या आपको वास्तव में फैंसी सामान की आवश्यकता होगी:

  1. यदि दोनों stdout और stderr को एक फ़ाइल पर रीडायरेक्ट किया गया था (एक ही फ़ाइल नहीं!) और दोनों फ़ाइलें FUSE वॉल्यूम पर थीं, तो FUSE मॉड्यूल प्रत्येक एकल लेखन को टाइमस्टैम्प के साथ चिह्नित कर सकता है ताकि एक दूसरा एप्लिकेशन डेटा को सही ढंग से सॉर्ट कर सके और इसे संयोजित कर सके असली आउटपुट फ़ाइल के लिए। या आप डेटा को चिह्नित नहीं करते हैं, लेकिन मॉड्यूल संयुक्त आउटपुट फ़ाइल बनाते हैं। सबसे शायद कोई FUSE मॉड्यूल अभी तक नहीं है जो यह करता है ...
  2. Stdout और Stderr दोनों को निर्देशित किया जा सकता है /dev/null। एप्लिकेशन के आउटपुट को इसके माध्यम से चलाकर अलग किया जाएगा strace -f -s 32000 -e trace=write। आपको उस मामले में भागने को उलटना होगा। यह कहने की आवश्यकता नहीं है कि एप्लिकेशन का पता लगाकर तेजी से नहीं चलता है।
  3. शायद एक ही मौजूदा, सरल FUSE मॉड्यूल का उपयोग करके और एप्लिकेशन के बजाय मॉड्यूल का पता लगाकर पहुंचा जा सकता है। यह अनुप्रयोग को ट्रेस करने से अधिक तेज़ हो सकता है क्योंकि (या यों कहें तो: यदि) मॉड्यूल में संभवतः अनुप्रयोग की तुलना में बहुत कम syscalls है।
  4. यदि एप्लिकेशन को स्वयं संशोधित किया जा सकता है: एप्लिकेशन को प्रत्येक आउटपुट के बाद रोका जा सकता है (लेकिन मुझे लगता है कि यह केवल अंदर से संभव है) और केवल s सिग्नल (SIGUSR1 या SIGCONT) प्राप्त करने के बाद जारी रखें। पाइप से पढ़ने वाले एप्लिकेशन को नए डेटा के लिए पाइप और फ़ाइल दोनों की जांच करनी होगी और प्रत्येक नए डेटा के बाद सिग्नल भेजना होगा। इस तरह के अनुप्रयोग के आधार पर यह स्ट्रेस विधि की तुलना में तेज़ या धीमा हो सकता है। FUSE अधिकतम गति समाधान होगा।

1
बाह। लिखने के बीच में मुझे पकड़ो ठीक वही जवाब क्यों नहीं।
केविन

2
NB की यह एक दौड़ की स्थिति है जो बाहर / गलत लाइनों को स्वैप करने की संभावना का परिचय देती है, लेकिन मुझे नहीं लगता कि इससे बचा जा सकता है।
केविन

1
@ केविन जो हम में से सबसे अच्छा होता है, मैं इससे पहले पीड़ित हो चुका हूं और उसने लगभग "मुझे दिखाओ कि कोई व्यक्ति" फीचर लिख रहा है (जो कि जटिल होगा, हालांकि)। यह मुझे लगता है कि दौड़ की स्थिति केवल तब होती है जब फ़ाइल (stdout) के लिए एक लेखन पाइपलाइन के लिए लिखने के बाद होता है।
हौके लैजिंग

नहीं भेजने दोनों कि चाहेंगे stdoutऔर stderrकरने के लिए tee, या मैं कुछ याद आ रही है? मुझे लगता है कि ओपी की आवश्यकता tee stderrकेवल करने के लिए है ।
जोसेफ आर।

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