2017-02-22 9 views
5

मेरे पास एक बहुत लंबी बाश स्क्रिप्ट है जो कुछ बाहरी कमांड (git clone, wget, apt-get और अन्य) को आमंत्रित करती है जो मानक आउटपुट में बहुत सी चीजें प्रिंट करती हैं।मैं शैल स्क्रिप्ट के अंदर लॉग वर्बोजिटी कैसे प्रबंधित करूं?

मैं चाहता हूं कि स्क्रिप्ट में कुछ वर्बोजिटी विकल्प हों, इसलिए यह बाहरी कमांड से सबकुछ प्रिंट करता है, इसका एक सारांशित संस्करण (उदाहरण के लिए "निर्भरता स्थापित करना ...", "संकलन ..." आदि) या कुछ भी नहीं बिलकुल। लेकिन मैं अपने सभी कोड को छेड़छाड़ किए बिना कैसे कर सकता हूं?

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

दूसरा समाधान सभी आउटपुट को बाहरी फाइलों में भेजना है, और स्क्रिप्ट की शुरुआत में तर्कों को पार्स करते समय, tail -f उस फ़ाइल पर वर्बोजिटी निर्दिष्ट होने पर चल रहा है। यह लागू करना बहुत आसान होगा, लेकिन मुझे बहुत हैकी लगता है और मैं इसके प्रदर्शन प्रभाव के बारे में चिंतित हूं।

कौन सा बेहतर है? मैं अन्य समाधानों के लिए भी खुला हूं।

+1

आप उपयोग कर '-x सेट माना जाता है '? इस स्क्रिप्ट को अपनी स्क्रिप्ट के शीर्ष पर कॉल करें और प्रत्येक निम्न आदेश को प्रतिबिंबित किया जाएगा। आप इसे 'सेट + एक्स' के साथ बंद कर सकते हैं। –

+1

इसके अतिरिक्त, जब भी कोई आदेश शून्य-शून्य स्थिति से बाहर निकलता है तो आप स्क्रिप्ट को निरस्त करने के लिए 'set -e' का उपयोग भी कर सकते हैं। –

+0

नहीं, मुझे वह चाहिए जो मुझे चाहिए। मुझे पता है कि मैं कौन से आदेश चला रहा हूं, मैं बस अपनी स्क्रिप्ट को उनके द्वारा आउटपुट की सभी चीजों को प्रिंट करने का तरीका चाहता हूं या कुछ विकल्पों के आधार पर नहीं। वास्तविक कोड की तुलना में यह उपयोगकर्ता की अधिक चीज़ है। – Ocab19

उत्तर

4

आपके पास पहले से ही आपके प्रश्न (एक रैपर फ़ंक्शन) में सबसे साफ विचार प्रतीत होता है, लेकिन आपको लगता है कि यह गन्दा होगा। मैं आपको पुनर्विचार का सुझाव दूंगा। वह ऐसा दिखाई दे सकता है (जरूरी नहीं कि एक पूर्ण समाधान है, केवल आपके मूल विचार देने के लिए):

#!/bin/bash 

# Argument 1 : Logging level for that command 
# Arguments 2... : Command to execute 
# Output suppressed if command level >= current logging level 
log() 
{ 
if 
    (($1 >= logging_level)) 
then 
    "${@:2}" >/dev/null 2>&1 
else 
    "${@:2}" 
fi 
} 

logging_level=2 

log 1 command1 and its args 
log 2 command2 and its args 
log 3 command4 and its args 

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

+0

मुझे अभी भी यकीन नहीं है कि मेरे द्वारा चलाए जाने वाले प्रत्येक आदेश में 'लॉग' जोड़ना सबसे साफ समाधान है। मुझे चिंता है कि अन्य लोगों को इस तरह कोड पढ़ने में परेशानी होगी। लेकिन ऐसा कोई बेहतर तरीका नहीं है, इसलिए मुझे लगता है कि मैं – Ocab19

+0

@ ओकैब 1 9 में इस के साथ जा रहा हूं - कृपया मेरे [answer] में 'log_debug_file' और' log_verbose_file' फ़ंक्शन देखें) (http://stackoverflow.com/एक/42426680/6,862,601)। इनके साथ, हम "लॉग 1" आदि जैसे निर्माण के कारण अव्यवस्था/पठनीयता हानि को खत्म कर सकते हैं, प्रत्येक कमांड के लिए प्रीफ़िक्स किया गया जिसका आउटपुट हमें थ्रॉटल करने की आवश्यकता है। लेकिन आउटपुट को रीडायरेक्ट करना और फिर लॉग फ़ंक्शन को कॉल करना अव्यवस्था है। – codeforester

1

समाधान 1. अतिरिक्त फ़ाइल वर्णनकर्ताओं का उपयोग करने पर विचार करें। चयनित वर्बोजिटिटी के आधार पर आवश्यक फ़ाइल डिस्क्रिप्टर को STDOUT या/dev/null पर पुनर्निर्देशित करें। अपनी स्क्रिप्ट में प्रत्येक कथन के आउटपुट को इसके महत्व के अनुरूप फ़ाइल डिस्क्रिप्टर पर रीडायरेक्ट करें। https://unix.stackexchange.com/a/218355 पर एक नज़र डालें। दो पैरामीटर, कुछ इस तरह के साथ एक सहायक स्क्रिप्ट को अपनी स्क्रिप्ट में हर बयान के

1

समाधान 2.

सेट $ required_verbosity और पाइप STDOUT:

बयान | लॉगर actual_verbosity $ required_verbosity

लॉगर स्क्रिप्ट में STDOUT (या लॉग फ़ाइल, जो भी हो) एसटीडीआईएन को प्रतिबिंबित करें यदि $ actual_verbosity> = $ required_verbosity।

4

थोड़ा और अधिक @ फ्रेड के विचार पर सुधार करना है, हम एक छोटे से प्रवेश पुस्तकालय इस तरह से बना सकते हैं:

declare -A _log_levels=([FATAL]=0 [ERROR]=1 [WARN]=2 [INFO]=3 [DEBUG]=4 [VERBOSE]=5) 
declare -i _log_level=3 
set_log_level() { 
    level="${1:-INFO}" 
    _log_level="${_log_levels[$level]}" 
} 

log_execute() { 
    level=${1:-INFO} 
    if (($1 >= ${_log_levels[$level]})); then 
    "${@:2}" >/dev/null 
    else 
    "${@:2}" 
    fi 
} 

log_fatal() { ((_log_level >= ${_log_levels[FATAL]})) && echo "$(date) FATAL $*"; } 
log_error() { ((_log_level >= ${_log_levels[ERROR]})) && echo "$(date) ERROR $*"; } 
log_info() { ((_log_level >= ${_log_levels[INFO]})) && echo "$(date) INFO $*"; } 
log_debug() { ((_log_level >= ${_log_levels[DEBUG]})) && echo "$(date) DEBUG $*"; } 
log_verbose() { ((_log_level >= ${_log_levels[VERBOSE]})) && echo "$(date) VERBOSE $*"; } 

# functions for logging command output 
log_debug_file() { ((_log_level >= ${_log_levels[DEBUG]})) && [[ -f $1 ]] && echo "=== command output start ===" && cat "$1" && echo "=== command output end ==="; } 
log_verbose_file() { ((_log_level >= ${_log_levels[VERBOSE]})) && [[ -f $1 ]] && echo "=== command output start ===" && cat "$1" && echo "=== command output end ==="; } 

चलो कहते हैं कि इसके बाद के संस्करण स्रोत एक पुस्तकालय logging_lib बुलाया फ़ाइल में है करते हैं।

#!/bin/bash 

source /path/to/lib/logging_lib.sh 

set_log_level DEBUG 

log_info "Starting the script..." 

# method 1 of controlling a command's output based on log level 
log_execute INFO date 

# method 2 of controlling the output based on log level 
date &> date.out 
log_debug_file date.out 

log_debug "This is a debug statement" 
... 
log_error "This is an error" 
... 
log_fatal "This is a fatal error" 
... 
log_verbose "This is a verbose log!" 

इस उत्पादन में परिणाम होगा::

Fri Feb 24 06:48:18 UTC 2017 INFO Starting the script... 
Fri Feb 24 06:48:18 UTC 2017 
=== command output start === 
Fri Feb 24 06:48:18 UTC 2017 
=== command output end === 
Fri Feb 24 06:48:18 UTC 2017 DEBUG This is a debug statement 
Fri Feb 24 06:48:18 UTC 2017 ERROR This is an error 
Fri Feb 24 06:48:18 UTC 2017 FATAL This is a fatal error 

हम देख सकते हैं, log_verbose लॉग स्तर के बाद से किसी भी उत्पादन का उत्पादन नहीं किया श, हम इसे एक नियमित रूप से खोल स्क्रिप्ट में इस तरह से इस्तेमाल कर सकते हैं DEBUG पर है, VERBOSE के नीचे एक स्तर। हालांकि, log_debug_file date.out ने उत्पादन का उत्पादन किया और log_execute INFO किया, चूंकि लॉग स्तर DEBUG पर सेट है, जो> = INFO है।

आधार के रूप में इस का उपयोग करना, हम भी अगर हम और भी ठीक ट्यूनिंग की जरूरत आदेश रैपर लिख सकते हैं:

git_wrapper() { 
    # run git command and print the output based on log level 
} 
जगह में इन के साथ

, स्क्रिप्ट एक तर्क --log-level level लेने के लिए है कि निर्धारित कर सकते हैं बढ़ाया जा सकता है लॉग वर्बोसिटी के साथ इसे चलाना चाहिए।


अगर कोई क्यों कुछ चर उपरोक्त कोड में रेखांकित एक प्रमुख के साथ नाम हैं के बारे में उत्सुक है, इस पोस्ट देखें:

+0

इस पर @ charlesduffy के विचार प्राप्त करना बहुत अच्छा है। – codeforester

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