2013-12-13 9 views
5

से बाहर निकलने की स्थिति के लिए जांच कर रहा है मुझे एक समस्या है कि बहु-पाइप कमांड श्रृंखला में एक निश्चित कमांड ने त्रुटि डाली है या नहीं। आमतौर पर यह जांचना मुश्किल नहीं है लेकिन न तो set -o pipefail और न ही ${PIPESTATUS[@]} मेरे मामले में काम करता है। सेटअप इस तरह है:बैश: मल्टी-पाइप कमांड चेन

cmd="$snmpcmd $snmpargs $agent $oid | grep <grepoptions> for_stuff | cut -d',' f$fields | sed 's/ubstitute/some_other_stuff/g'" 

नोट -1: कमांड का परीक्षण पूरी तरह से किया गया था और पूरी तरह से काम करता है।

अब, मैं उस आदेश के आउटपुट को procdata नामक सरणी में संग्रहीत करना चाहता हूं। इस प्रकार, मैंने किया था:

declare -a procdata 
procdata=($(eval $cmd)) 

नोट -2: क्योंकि अन्यथा $snmpcmd एक invalid option -- <grepoption> त्रुटि क्योंकि <grepoption> एक $snmpcmd विकल्प स्पष्ट रूप से नहीं है जो कोई मतलब नहीं है के साथ फेंकता eval आवश्यक है। इस चरण में मैं इसे $snmpcmd के साथ एक बग मानता हूं लेकिन यह एक और शो है ...

यदि कोई त्रुटि उत्पन्न होती है, तो procdata खाली हो जाएगा। हालांकि, यह दो अलग-अलग कारणों से खाली हो सकता है: या तो $snmpcmd (उदा। टाइमआउट) को निष्पादित करते समय त्रुटि हुई या grep यह नहीं ढूंढ सका कि वह क्या ढूंढ रहा था। समस्या यह है कि, मुझे इन दो मामलों के बीच अंतर करने और उन्हें अलग से संभालने में सक्षम होना चाहिए।

इस प्रकार, set -o pipefail कोई विकल्प नहीं है क्योंकि यह किसी भी त्रुटि का प्रचार करेगा और मैं अंतर नहीं कर सकता कि पाइप का कौन सा हिस्सा असफल रहा। दूसरी ओर echo ${PIPESTATUS[@]}procdata=($(eval $cmd)) के बाद हमेशा 0 है, भले ही मेरे पास कई पाइप हैं!? फिर भी अगर मैं तुरंत कमांड को प्रॉम्प्ट पर निष्पादित करता हूं और तुरंत echo ${PIPESTATUS[@]} पर कॉल करता हूं, तो यह सभी पाइपों के बाहर निकलने की स्थिति को सही तरीके से देता है।

मुझे पता है कि मैं त्रुटि स्ट्रीम को बाध्य करने के लिए बाध्य कर सकता हूं लेकिन मुझे यह देखने के लिए हेरिस्टिक विधियों का उपयोग करना होगा कि procdata में तत्व वैध या त्रुटि संदेश हैं और मैं झूठी सकारात्मक प्राप्त करने का जोखिम चलाता हूं। मैं /dev/null पर पाइप स्टडआउट भी पा सकता हूं और केवल त्रुटि स्ट्रीम को कैप्चर कर सकता हूं और जांच सकता हूं कि ${#procdata[@]} -eq 0 है या नहीं। लेकिन मुझे वास्तविक डेटा प्राप्त करने के लिए कॉल दोहराना होगा और पूरा आदेश समय महंगा होगा (सीए 3-5)। मैं इसे दो बार फोन नहीं करना चाहता। या मैं त्रुटियों को लिखने के लिए एक अस्थायी फ़ाइल का उपयोग कर सकता हूं लेकिन मैं फ़ाइलों को बनाने/हटाने के ऊपरी हिस्से के बिना इसे करूंगा।

कोई विचार मैं बैश में यह काम कैसे कर सकता हूं?

धन्यवाद

पुनश्च:

$ echo $BASH_VERSION 
4.2.37(1)-release 

उत्तर

3

चीजों की एक संख्या यहाँ:

(1) जब आप कहते हैं कि eval $cmd और पाइप लाइन में निहित में प्रक्रियाओं के बाहर निकलने के मूल्यों को प्राप्त करने का प्रयास कमांड $cmd, echo "${PIPESTATUS[@]}" में केवलeval के लिए बाहर निकलने की स्थिति होगी। eval के बजाय, आपको पूर्ण कमांड लाइन की आपूर्ति करने की आवश्यकता होगी।

(2) आपको चरम पर पाइपलाइन के आउटपुट को निर्दिष्ट करते समय PIPESTATUS प्राप्त करने की आवश्यकता है। ऐसा करने का प्रयास करना बाद में काम नहीं करेगा।


उदाहरण के लिए, आप कह सकते हैं:

foo=$(command | grep something | command2; echo "${PIPESTATUS[@]})" 

इस पाइप लाइन के उत्पादन और चर foo में PIPESTATUS सरणी कैप्चर करता है।

आप कह कर एक सरणी में आदेश उत्पादन हो सकता है:

result=($(head -n -1 <<< "$foo")) 

और

tail -1 <<< "$foo" 
+0

कह मैं एक ही सोचा था द्वारा PIPESTATUS सरणी। दुर्भाग्यवश यह काम नहीं करता है लेकिन मुझे यकीन नहीं है कि क्यों। मैं सटीक आदेश पोस्ट करता हूं क्योंकि मुझे स्पष्ट दिखाई नहीं दे रहा है: – user3040975

+0

'स्थानीय cmdargs =" - CHF, -m $ mibs -v $ snmpver -c $ समुदाय $ एजेंट "; स्थानीय procdatacmd = "$ tblcmd $ cmdargs $ proc_table"; procdatacmd + = "| कट-डी ',' -एफ $ फ़ील्ड | grep -we -e | सॉर्ट | uniq -c | sed's/^ * \ | \" // g; s//,/g ' ; echo $ {PIPESTATUS [@]} "'। फिर मैं करता हूं: 'घोषित करें- एक procdata = ($ (head -n -1 <<< $ procdatacmd))। आउटपुट खाली है ... बस कुछ भी नहीं। और एजेंट पर चल रहे हैं और चल रहे हैं। क्या ... – user3040975

+0

@ user3040975 आप उपरोक्त पंक्ति में किसी भी कमांड को _running_ प्रतीत नहीं करते हैं। – devnull

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