कमांड लाइन से पाइप के बिना टी का उपयोग करने के लिए बल बैश स्क्रिप्ट


20

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

मेरे पास एक फ़ाइल script.sh है :

#!/bin/bash
init
do_something_that_outputs_stuff_to_STDOUT
launch_applications_that_output_to_STDOUT
fini

और मैं हर बार टाइप किए बिना एक फ़ाइल script.log को STDOUT की प्रतिलिपि बनाना चाहूंगा./script.sh | tee script.log

धन्यवाद, टॉम


मुझे यह पहले नहीं कहने के लिए खेद है, लेकिन स्क्रिप्ट लंबी है, यही वजह है कि मैं एक सरल समाधान ढूंढ रहा हूं। लागू करना | प्रत्येक पंक्ति के लिए टी बहुत अधिक है।
टॉम

जवाबों:


15

मुझे डेनिस का काम करने के लिए बहुत सरल वन-लाइनर नहीं मिला, इसलिए यहां बहुत अधिक जटिल विधि है। मैं उसकी पहली कोशिश करूँगा।

जैसा कि उल्लेख किया गया है, आप संपूर्ण स्क्रिप्ट के लिए मानक त्रुटि और मानक को पुनर्निर्देशित करने के लिए निष्पादन का उपयोग कर सकते हैं। जैसे:
exec > $LOGFILE 2>&1 यह सभी स्टीडर और स्टडआउट को $ लोगीमर में आउटपुट करेगा।

अब, चूंकि आप इसे कंसोल के साथ-साथ लॉगफ़ाइल में भी प्रदर्शित करना चाहते हैं, इसलिए आपको लिखने के लिए निष्पादन के लिए नामित पाइप, और पढ़ने के लिए टी का उपयोग करना होगा।
(डेनिस का वन-लाइनर तकनीकी रूप से भी ऐसा करता है, हालांकि स्पष्ट रूप से एक अलग तरीके से) पाइप खुद के साथ बनाया गया है mkfifo $PIPEFILE। फिर निम्नलिखित करें।

# टी लॉग लिखना शुरू करें, लेकिन हमारे नामित पाइप से इसके इनपुट को खींचते हुए।
$ $ लोगो <$ PIPEFILE &

# वेट कमांड के लिए टी की प्रक्रिया आईडी पर कब्जा।
TEEPID = $!

# हमारे नामित पाइप के लिए बाकी स्टडर और स्टडआउट को पुनर्निर्देशित करें।
निष्पादित> $ PIPEFILE 2> और 1

इको "अपनी आज्ञा यहाँ बनाएँ"
गूंज "उनके सभी मानक बाहर हो जाएंगे।"
इको "तो उनकी मानक त्रुटि होगी"> और 2

# stderr और stdout फ़ाइल डिस्क्रिप्टर को बंद करें।
1> & - 2> & - निष्पादित करें

# टी के खत्म होने का इंतजार करें क्योंकि अब पाइप का दूसरा छोर बंद हो चुका है।
$ TEEPID की प्रतीक्षा करें

यदि आप पूरी तरह से बनना चाहते हैं, तो आप अपनी स्क्रिप्ट के आरंभ और अंत में नामित पाइप फ़ाइल बना और नष्ट कर सकते हैं।

रिकॉर्ड के लिए, मैंने एक यादृच्छिक व्यक्ति के बहुत जानकारीपूर्ण ब्लॉग पोस्ट से इस पर प्रकाश डाला: ( संग्रहीत संस्करण )


यह सब साइबर में काम नहीं करता है। :-(
docwhat

यह पोस्ट शिक्षित करने का अच्छा काम करती है। आपका बहुत बहुत धन्यवाद।
फेलिप अल्वारेज

27

बस इसे अपनी स्क्रिप्ट की शुरुआत में जोड़ें:

exec > >(tee -ia script.log)

यह script.logपिछले आउटपुट को छोड़ते हुए, फ़ाइल के लिए stdout में भेजे गए सभी आउटपुट को जोड़ देगा । आप ताजा हर बार स्क्रिप्ट चलाया जाता है शुरू करने के लिए चाहते हैं, बस जोड़ने rm script.logसे पहले सही execआदेश या हटाने -aसे teeआदेश।

-iविकल्प का कारण बनता है teeव्यवधान संकेतों की अनदेखी करने और अनुमति दे सकता है teeएक और अधिक पूरा उत्पादन सेट को पकड़ने के लिए।

इस पंक्ति को सभी त्रुटियों को पकड़ने के लिए (एक अलग फ़ाइल में) जोड़ें:

exec 2> >(tee -ia scripterr.out)

कई >प्रतीकों के बीच रिक्त स्थान महत्वपूर्ण हैं।


बहुत ही रोचक उपाय।
35फिंक

2
यह मेरे द्वारा किए गए सभी बकवास की तुलना में इसे करने का एक बहुत ही सुंदर तरीका है। लेकिन जब मैं इसमें उन दो पंक्तियों के साथ एक स्क्रिप्ट बनाता हूं, तो यह लटका रहता है, और कभी ठीक से बाहर नहीं निकलता है।
क्रिस्टोफर कारेल

बैश का क्या संस्करण?
अगली सूचना तक रोक दिया गया।

GNU बैश, संस्करण 3.2.25 (1) RHEL5.3 इंस्टॉल के हिस्से के रूप में। ऐसा लगता है कि यह आधिकारिक रिपॉजिटरी का नवीनतम संस्करण है।
क्रिस्टोफर कारेल

मैंने बस इसे बैश 3.2.49 (23) -grease में cygwin के तहत आज़माया और फाइल डिस्क्रिप्टर त्रुटियों को मिला। मैं उबंटू 9.10 में बैश 4.0.33 (1) में काम करता हूं, हालांकि, यह बैश 4 चीज हो सकती है।
अगली सूचना तक रोक दिया गया।

6

यह पहले डेनिस विलियमसन द्वारा पोस्ट किए गए उत्तर का संयुक्त संस्करण है। सही क्रम में script.log के लिए दोनों गलत और std को जोड़ता है।

इस लाइन को अपनी स्क्रिप्ट की शुरुआत में जोड़ें:

exec > >(tee -a script.log) 2>&1

>संकेतों के बीच की जगह पर ध्यान दें । GNU बैश पर मेरे लिए काम करता है, संस्करण 3.2.25 (1) -release (x86_64-redhat-linux-gnu)


5

मुझे लगता है कि एक और दृष्टिकोण कुछ इस तरह है:

#!/bin/bash

# start grouping at the top
{ 
    # your script goes here
    do_something_that_outputs_stuff_to_STDOUT
    launch_applications_that_output_to_STDOUT

# and at the bottom, redirect everything from the grouped commands
} 2>&1 | tee script.log 

3

यदि आप आउटपुट की एक प्रति चाहते हैं, तो आप teeइस तरह से उपयोग कर सकते हैं :

  #!/bin/bash
  init
  do_something_that_outputs_stuff_to_STDOUT | tee script.log
  launch_applications_that_output_to_STDOUT | tee -a script.log
  fini

हालाँकि यह केवल script.log पर लॉगआउट करेगा। यदि आप यह सुनिश्चित करना चाहते हैं कि दोनों stderr और stdout पुनर्निर्देशित हैं, तो उपयोग करें:

  #!/bin/bash
  init
  do_something_that_outputs_stuff_to_STDOUT 2>&1 | tee script.log
  launch_applications_that_output_to_STDOUT 2>&1 | tee -a script.log
  fini

तुम भी इसे एक छोटे से समारोह के साथ एक अच्छा बना सकते हैं:

  #!/bin/bash

  LOGFILE="script.log"
  # Wipe LOGFILE if you don't want to add to it at each run
  rm -f "$LOGFILE"

  function logcmd() {
        local cmd="$1" logfile=${LOGFILE:-script.log} # Use default value if unset earlier

        # Launch command, redirect stderr to stdout and append to $logfile
        eval '$cmd' 2>&1 | tee -a "$logfile"
  }

  init
  logcmd "do_something_that_outputs_stuff_to_STDOUT"
  logcmd "launch_applications_that_output_to_STDOUT"
  fini

अच्छा उत्तर। अगर वह वास्तव में केवल स्टडआउट की परवाह करता है, तो मैं बस 2>&1बाहर निकलूंगा और इसे टी करने के लिए पाइप करूंगा ।
डेवपैरिलो

यह सच है, मैंने केवल स्टॉडर को शामिल किया क्योंकि इगोर के पिछले उत्तर ने इसे पुनर्निर्देशित किया और मुझे लगा कि यह एक अच्छा विचार है।
16फिंक

1

आप बस इसका उपयोग करेंगे:

script logfile.txt
your script or command here

यह सब कुछ उस लॉग में, सब कुछ, साथ ही स्क्रीन पर प्रदर्शित करने के लिए आउटपुट करता है। यदि आप पूर्ण आउटपुट चाहते हैं, तो यह कैसे करना है।

और आप स्क्रिप्ट को फिर से दोहरा सकते हैं यदि आप आलसी हैं।


यह नोट करना अच्छा हो सकता है कि scriptएक पैकेज है, उदाहरण के लिए। sudo apt-get install scriptइसे डेबियन फ्लेवर्ड डिस्ट्रोस पर स्थापित करने के लिए , इसके अलावा script -ac 'command opts' ~/Documents/some_log.scriptटर्मिनल के भीतर कुछ इस तरह की समीक्षा की जा सकती है strings ~/Documents/some_log.script | more; फिर से खेलने / देखने के कट्टर तरीकों के लिए अनुमति देने के लिए इंजेक्शन लगाने वाली stringsकुछ चीजों को पूर्व-साफ करने का एक सरल तरीका हो । अन्यथा एक ठोस जवाब @Phishy, ​​क्योंकि इंटरैक्टिव चीजों को भी संरक्षित करता है। script script
S0AndS0

0
#!/bin/bash
init
do_something_that_outputs_stuff_to_STDOUT > script.log 2>&1
launch_applications_that_output_to_STDOUT >> script.log 2>&1
fini

आप इसके बारे में और अधिक देख सकते हैं कि यह यहाँ कैसे काम करता है: http://www.xaprb.com/blog/2006/06/06/what-does-devnull-21-mean/


1
मैंने इगोर के जवाब में दूसरी पंक्ति में दूसरी पंक्ति को जोड़ा ताकि यह पहली पंक्ति में लिखे गए लॉग को मिटा न सके।
डग हैरिस

1
वह हालांकि एक प्रति चाहता है, इसलिए उसे उपयोग करने की आवश्यकता है tee
ℝफिंक

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