शेल स्क्रिप्ट के अंदर स्क्रीन और फाइल दोनों में टेक्स्ट कैसे आउटपुट करें?


49

वर्तमान में मेरे पास एक शेल स्क्रिप्ट है जो लॉग फ़ाइल में इस तरह से संदेश भेजता है:

log_file="/some/dir/log_file.log"
echo "some text" >> $log_file
do_some_command
echo "more text" >> $log_file
do_other_command

इस स्क्रिप्ट को निष्पादित करते समय, स्क्रीन पर कोई आउटपुट नहीं होता है, और, चूंकि मैं सर्वर को पोटीन के माध्यम से कनेक्ट कर रहा हूं, मुझे एक और कनेक्शन खोलना होगा और "tail -f log_file_path.log" करना होगा, क्योंकि मैं रनिंग को समाप्त नहीं कर सकता हूं स्क्रिप्ट और मैं वास्तविक समय में आउटपुट देखना चाहते हैं।

जाहिर है, मैं जो चाहता हूं, वह यह है कि टेक्स्ट मैसेज स्क्रीन और फाइल में प्रिंट होते हैं, लेकिन मैं इसे एक लाइन में करना चाहता हूं, दो लाइन में नहीं, जिनमें से एक में फाइल को रीडायरेक्ट नहीं करना है।

इसे कैसे प्राप्त किया जाए?

जवाबों:


71

यह काम:

command | tee -a "$log_file"

teeफ़ाइल में इनपुट बचाता है ( -aअधिलेखित करने के बजाय एपेंड करने के लिए उपयोग ), और इनपुट को मानक आउटपुट पर भी कॉपी करता है।


8

आप यहाँ-डॉक्टर का उपयोग कर सकते हैं और। यह एक कुशल, POSIX- अनुकूल सामान्य कलेक्टर मॉडल के लिए स्रोत है।

. 8<<-\IOHERE /proc/self/fd/8

command
 
fn() { declaration ; } <<WHATEVER
# though a nested heredoc might be finicky
# about stdin depending on shell
WHATEVER
cat -u ./stdout | ./works.as >> expect.ed
IOHERE

जब आप heredoc खोलते हैं तो आप शेल को IOHERE इनपुट टोकन के साथ संकेत देते हैं कि यह आपके इनपुट को आपके द्वारा निर्दिष्ट किए गए फ़ाइल-डिस्क्रिप्टर तक रीडायरेक्ट करेगा जब तक कि यह आपके सीमक टोकन के दूसरे छोर का सामना नहीं करता है। मैंने चारों ओर देखा है, लेकिन मैंने पुनर्निर्देशन fd नंबर के उपयोग के कई उदाहरण नहीं देखे हैं जैसा कि मैंने ऊपर heredoc ऑपरेटर के साथ संयोजन में दिखाया है, हालांकि इसका उपयोग POSIX मूल शेल-कमांड दिशानिर्देशों में स्पष्ट रूप से निर्दिष्ट है। ज्यादातर लोग इसे सिर्फ स्टडिन और शूट पर इंगित करते हैं, लेकिन मुझे लगता है कि इस तरह से सोर्सिंग स्क्रिप्टलेट्स स्टैडेन और घटक ऐप्स को अवरुद्ध I / o रास्तों के बारे में शिकायत करने से बचा सकते हैं।

Heredoc की सामग्री को आपके द्वारा निर्दिष्ट फ़ाइल डिस्क्रिप्टर पर स्ट्रीम किया जाता है, जो तब शेल-कोड के रूप में व्याख्या की जाती है और इसके द्वारा निष्पादित की जाती है। बिलिन, लेकिन विशिष्ट पथ निर्दिष्ट किए बिना नहीं। । यदि / proc / self पाथ आपको परेशानी / dev / fd / n या / proc / $ $ देता है। यह वही तरीका पाइप पर काम करता है, जिस तरह से:

cat ./*.sh | . /dev/stdin

शायद कम से कम उतना ही नासमझ है जितना दिखता है। आप श के साथ भी ऐसा कर सकते हैं, निश्चित रूप से, लेकिन इसका उद्देश्य वर्तमान शेल वातावरण में निष्पादित करना है, जो संभवतः आप चाहते हैं, और, आपके शेल के आधार पर, हेरेडोक के साथ काम करने की संभावना बहुत अधिक है एक मानक अनाम पाइप के साथ।

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

. 5<<EOIN /dev/fd/5 |\ 
    tee -a ./log.file | cat -u >$(tty)
script
 
more script
EOIN

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

आप दूसरे उदाहरण में लापता बैकस्लैश उद्धरण पर भी सवाल उठा सकते हैं। आपके कूदने से पहले यह हिस्सा समझना महत्वपूर्ण है और यह आपको कुछ विचार दे सकता है कि इसका उपयोग कैसे किया जा सकता है। एक उद्धृत हेरेडोक सीमक (अब तक हमने IOHERE और EOIN का उपयोग किया है, और पहला मैंने एक बैकस्लैश के साथ उद्धृत किया है, हालांकि 'सिंगल' या "डबल" कोट्स एक ही उद्देश्य से काम करेंगे) शेल को किसी भी प्रकार के विस्तार पर प्रदर्शन करने से रोक देगा सामग्री, लेकिन एक निर्विवाद सीमक अपनी सामग्री को विस्तार के लिए खुला छोड़ देगा। इसके परिणाम जब आपके वंशानुगत होते हैं। खट्टे नाटकीय हैं:

. 3<<HD ${fdpath}/3
: \${vars=$(printf '${var%s=$((%s*2))},' `seq 1 100`)} 
HD
echo $vars
> 4,8,12 
echo $var1 $var51
> 4 104

क्योंकि मैंने हेरेडोक सीमक को उद्धृत नहीं किया था, इसलिए शेल ने सामग्री का विस्तार किया, क्योंकि इसे पढ़ने के लिए और परिणामस्वरूप फाइल डिस्क्रिप्टर को सेवा देने से पहले। निष्पादन हेतु। इसके परिणामस्वरूप अनिवार्य रूप से आदेश दो बार पार्स हो गए - वैसे भी विस्तार योग्य। क्योंकि मैं $ vars पैरामीटर विस्तार के बैकस्लैश उद्धृत करता हूं, शेल ने पहले पास पर अपनी घोषणा को नजरअंदाज कर दिया और केवल बैकस्लैश को हटा दिया ताकि पूरे प्रिंटफ विस्तारित सामग्री का मूल्यांकन जब अशक्त हो सके। दूसरी पास पर पटकथा लिखी।

यह कार्यक्षमता मूल रूप से वही है जो खतरनाक eval खोल बिलियन प्रदान कर सकता है, भले ही उद्धरण एक evered की तुलना में heredoc में संभालना बहुत आसान है, और उतना ही खतरनाक हो सकता है। जब तक आप इसकी सावधानीपूर्वक योजना नहीं बनाते हैं, तब तक "ईओएफ" सीमक को आदत के रूप में उद्धृत करना सबसे अच्छा है। बस केह रहा हू।

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

{ or ( command ) list ; } | tee -a ea.sy >>pea.sy

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

मज़े करो!


3

इंस्टॉल लॉग लिखने के लिए इंस्टॉल स्क्रिप्ट को संशोधित करते समय मुझे यह उत्तर मिला।

मेरी स्क्रिप्ट पहले से ही इको स्टेटमेंट्स से भरी है जैसे:

echo "Found OLD run script $oldrunscriptname"
echo "Please run OLD tmunsetup script first!"

और मैं इसे चलाने के लिए एक टीई स्टेटमेंट नहीं चाहता था (या किसी अन्य स्क्रिप्ट को टी के साथ मौजूदा कॉल करने के लिए), इसलिए मैंने यह लिखा है:

#!/bin/bash
# A Shell subroutine to echo to screen and a log file

LOGFILE="junklog"

echolog()
(
echo $1
echo $1 >> $LOGFILE
)


echo "Going"
echolog "tojunk"

# eof

इसलिए अब अपनी मूल स्क्रिप्ट में, मैं 'इको' को 'इकोलॉग' में बदल सकता हूं, जहां मुझे लॉग फाइल में आउटपुट चाहिए।

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