2010-05-20 19 views
12

स्क्रीन करने के लिए STDERR भी लिखें I कई आदेशों को चलाने के लिए, और सभी आउटपुट को लॉगफाइल पर कैप्चर करना चाहते हैं। मैं स्क्रीन पर किसी भी त्रुटि को मुद्रित करना चाहता हूं (या वैकल्पिक रूप से आउटपुट को किसी को मेल करें)।एक लॉगफाइल पर STDOUT और STDERR लिखें,

यहां एक उदाहरण है। निम्न आदेश तीन आदेश चलाएगा, और एक ही लॉगफाइल में सभी आउटपुट (STDOUT और STDERR) लिखेंगे। मामले में मैं की जरूरत है इसे बाद में --- मैं आमतौर पर जीता

  • STDERR और STDOUT सभी आदेशों के लिए एक लॉगफ़ाइल को जाता है,:

    { command1 && command2 && command3 ; } > logfile.log 2>&1 
    

    यहाँ क्या मैं इन आदेशों में से उत्पादन के साथ क्या करना चाहते है जब तक समस्याएं न हों तब तक यहां नज़र डालें।

  • स्क्रीन पर STDERR प्रिंट करें (या वैकल्पिक रूप से, पाइप से/बिन/मेल), ताकि कोई भी त्रुटि खड़ी हो और अनदेखा न हो।
  • यह अच्छा होगा अगर रिटर्न कोड अभी भी प्रयोग योग्य थे, ताकि मैं कुछ त्रुटि प्रबंधन कर सकूं। शायद मैं, यदि कोई त्रुटि हुई ईमेल भेजना चाहते हैं इस तरह:

    {command1 & & command2 & & command3; }> logfile.log 2> & 1 || mailx -s [email protected]

समस्या मैं में चलाने कि STDERR आई/ओ पुनर्निर्देशन दौरान संदर्भ खो देता है "वहाँ एक त्रुटि थी"। ए '2> & 1' एसटीडीईआरआर को एसटीडीओयूटी में परिवर्तित करेगा, और इसलिए यदि मैं 2> error.log

यहां कुछ juicier उदाहरण हैं, तो मैं त्रुटियों को नहीं देख सकता। आइए दिखाएं कि मैं कुछ परिचित निर्माण आदेश चला रहा हूं, लेकिन मैं नहीं चाहता कि पूरे निर्माण को सिर्फ एक त्रुटि के कारण रुकना है, इसलिए मैं 'रख-रखाव' ध्वज का उपयोग करता हूं।

{ ./configure && make --keep-going && make install ; } > build.log 2>&1 

या, यहाँ एक सरल (और शायद खराब) का निर्माण और तैनात स्क्रिप्ट, जो त्रुटि होने की स्थिति में जा रहा रखना होगा है।

{ ./configure && make --keep-going && make install && rsync -av --keep-going /foo devhost:/foo} > build-and-deploy.log 2>&1 

मुझे लगता है कि मैं चाहता हूँ Bash I/O Redirection किसी प्रकार शामिल है, लेकिन मैं इस को समझ नहीं सकता।

उत्तर

12
(./doit >> log) 2>&1 | tee -a log 

यह stdout ले जाएगा और इसे लॉग फ़ाइल में जोड़ देगा।

stderr तो stdout जो tee जो यह लॉग में संलग्न कर देता है (यदि आप बैश 4 कर रहे हैं, तो आप |& साथ 2>&1 | जगह ले सकता है) और stdout करने के लिए है जो या तो tty पर दिखाई देगा भेजता को पहुंचाया जाता है करने के लिए परिवर्तित हो जाएगी या किसी अन्य आदेश पर पाइप किया जा सकता है।

मैंने दोनों के लिए एपेंड मोड का उपयोग किया ताकि इस बात पर ध्यान दिए बिना कि शेल रीडायरेक्शन और tee फ़ाइल को खोलने के लिए, आप मूल को दूर नहीं करेंगे। उस ने कहा, यह संभव हो सकता है कि stderr/stdout एक अप्रत्याशित तरीके से interleaved है।

+0

आपका कोड काम करता है, लेकिन जैसे ही मैं कई आदेश चलाता हूं जैसे '(./doit && ./doit2 >> लॉग) 2> और 1 | tee -a log', फिर stitout और stderr दोनों doit और doit2 स्क्रीन पर मुद्रित है। –

+0

ऐसा लगता है कि अगर मैं ऐसा कुछ करता हूं: '({./doit && ./stdout.sh;} >> लॉग) 2> और 1 | tee -a log' –

+1

@StefanLasiewski - हाँ, फ़ाइल पुनर्निर्देशन केवल इसके तुरंत बाद कमांड पर लागू होता है। एक कम सबहेल में दो कमांड को समूहित करने के लिए आपका कामकाज सबसे आसान समाधान है; एक और uglier फिक्स प्रत्येक आदेश '(./doit >> लॉग और& ./doit2 >> लॉग) 2> और 1 के लिए stdout को पुनर्निर्देशित करना होगा। tee -a log' –

0

प्रयास करें:

command 2>&1 | tee output.txt 

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

command > stdout.txt >& stderr.txt 

command > stdout.txt |& program_for_stderr 

तो के कुछ संयोजन ऊपर आप के लिए काम करना चाहिए - जैसे आप एक फ़ाइल में stdout को सहेज सकते हैं, और एक फ़ाइल और पाइपिंग दोनों को एक प्रोग्राम (टीई के साथ) के लिए stderr।

+1

में आप सबसे पहले करने के लिए stdout और stderr भेजने के लिए ठीक है पर देखा जाएगा टर्मिनल और फ़ाइल दोनों, लेकिन बाद की दो पंक्तियां उन्हें विभिन्न स्थानों पर भेजने के लिए काम नहीं करतीं। '> Stdout.txt' हवाओं का कोई प्रभाव नहीं पड़ता है क्योंकि जब आप '> &' या '| &' का उपयोग करते हैं तो यह _both_ धाराओं को पुनर्निर्देशित करता है। –

+0

पहला और तीसरा आदेश काम नहीं करेगा, क्योंकि stderr को '2> और 1' द्वारा stdout पर रीडायरेक्ट किया जाता है। मेरा मतलब है "एसटीडीईआरआर ऊपर आई/ओ पुनर्निर्देशन के दौरान संदर्भ खो देता है"। बैश रेफरेंस मैनुअल का कहना है कि '| &' "' 2> और 1 | ' दूसरा आदेश स्क्रीन पर stderr मुद्रित नहीं करता है। –

1

आपके सिस्टम है/dev/fd/* नोड्स आप के रूप में यह कर सकते हैं:

(exec 5>logfile.txt ; { command1 && command2 && command3 ;} 2>&1 >&5 | tee /dev/fd/5) 

यह आपके लॉगफ़ाइल करने के लिए फ़ाइल वर्णनकर्ता 5 खोलता है। मानक त्रुटि के लिए निर्देशित मानक त्रुटि के साथ आदेश निष्पादित करता है, एफडी 5 और पाइप स्टडआउट (जो अब केवल stderr होता है) को निर्देशित मानक आउट करता है जो आउटपुट को fd 5 में डुप्लिकेट करता है जो लॉग फ़ाइल है।

+0

जब मैं आपका आदेश निष्पादित करता हूं, तो मेरे लॉगफाइल में केवल स्क्रीन पर दिखाई देने वाले त्रुटि संदेश होते हैं। stdout खो गया है। – tangens

+0

'tee -a/dev/fd/5' –

+0

आज़माएं यह भी काम करता है। हालांकि, मुझे यकीन नहीं है कि मैं क्यों समझता हूं। लेकिन मैंने इस तरह के एक आदेश की कोशिश की, और यह काम करता है: '(exec 5> logfile.txt; {date && ./doit && ./stdout.sh;} 2> और 1> और 5 | टीई/देव/एफडी/5) ' –

1

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

प्रारंभिक:

ओपन दो खिड़कियां (गोले, tmux सत्र, जो कुछ भी)

मैं कुछ परीक्षण फाइलों के साथ प्रदर्शन करेंगे, इसलिए परीक्षण फ़ाइलों को बनाने:

touch /tmp/foo /tmp/foo1 /tmp/foo2 
window1 में

:

mkfifo /tmp/fifo 

0</tmp/fifo cat - >/tmp/logfile 

फिर, विंडो 2:

में
(ls -l /tmp/foo /tmp/nofile /tmp/foo1 /tmp/nofile /tmp/nofile; echo successful test; ls /tmp/nofile1111) 2>&1 1>/tmp/fifo | tee /tmp/fifo 1>/dev/pts/2 

जहां आप /dev/pts/2 को प्रतिस्थापित करते हैं, जहां आप स्टेडर को प्रदर्शित करना चाहते हैं।

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

इस विधि के साथ, आउटपुट और त्रुटि का ऑर्डरिंग संरक्षित है, वाक्यविन्यास सरल और साफ है, और आउटपुट फ़ाइल में केवल एक ही संदर्भ है। इसके अलावा जहां भी आप चाहते हैं वहां stderr की अतिरिक्त प्रतिलिपि डालने में flexiblity है।

+0

यह अनिवार्य रूप से आर सैमुअल क्लैचकोस उत्तर के समान है। यह ऑर्डरिंग को भी सुरक्षित नहीं करता है। इसे कुछ सरल लिपि à la echo out 1 के साथ आज़माएं; इको गलती 2> और 2; 3 गूंजें; अपने ls सामान के बजाय गलती 4> और 2' गूंजें और आप देखेंगे। मुझे लगता है कि आपका उदाहरण काम करता है क्योंकि एलएस शुरू हो रहा है, टीई को कुछ सीपीयू चक्र मिलते हैं, लेकिन यह सिर्फ शुद्ध भाग्य है, कुछ असली दुनिया के साथ यह काम नहीं करेगा। – Marian

+0

मैं कल फिर से परीक्षण करूंगा, लेकिन जैसा कि मुझे याद है कि मैंने पहले ही कुछ कड़े परीक्षण किए हैं, जिसमें निरंतर परिणाम के साथ गूंज और अन्य आदेश शामिल हैं। –

0

अपनी स्क्रिप्ट

#!/bin/bash 
set -e 
outfile=logfile 

exec > >(cat >> $outfile) 
exec 2> >(tee -a $outfile >&2) 

# write your code here 

STDOUT और STDERR$outfile को लिखा जाएगा की शुरुआत में इस जोड़ने के लिए, केवल STDERR सांत्वना

संबंधित मुद्दे