यदि कमांड सफल होता है तो मैं केवल आउटपुट को कैसे दबा सकता हूं?


22

मैं आमतौर पर सफल होने वाले माध्यमिक आदेशों के उत्पादन को दबाकर एक स्क्रिप्ट के उत्पादन को सरल बनाना चाहता हूं।

हालाँकि, -qजब वे कभी-कभी विफल हो जाते हैं, तो उन पर उपयोग करने से आउटपुट छिप जाता है, इसलिए मेरे पास त्रुटि को समझने का कोई तरीका नहीं है। इसके अतिरिक्त, ये कमांड अपना आउटपुट लॉग ऑन करते हैं stderr

क्या एक कमांड के आउटपुट को दबाने का एक तरीका है केवल अगर यह सफल होता है ?

उदाहरण के लिए (लेकिन सीमित नहीं) कुछ इस तरह से:

mycommand | fingerscrossed

यदि सब ठीक हो जाता है, fingerscrossedतो आउटपुट को पकड़ता है और उसे छोड़ देता है। यह इसे मानक या त्रुटि आउटपुट (जो भी) के लिए गूँजता है।

जवाबों:


36

moreutils' chronicकमांड बस यही करता है:

chronic mycommand

निगल जाएगा mycommandके उत्पादन, जब तक यह विफल रहता है, जो मामले में उत्पादन प्रदर्शित होता है।


1
धन्यवाद। मुझे लगता है कि यह ज्यादातर यूनिक्स ओएस पर डिफ़ॉल्ट रूप से स्थापित नहीं है?
मैथ्यू नेपोली

1
शायद नहीं, हालांकि यह व्यापक रूप से पैक किया गया है इसलिए इसे स्थापित करना आसान होना चाहिए।
स्टीफन किट

1
डेबियन पैकेज में है moreutils। मेरे लिए अच्छा है, वैसे भी :)
टॉम जिक

6
ध्यान दें कि यह पूरे आउटपुट को मेमोरी में स्टोर करता है।
स्टीफन चेज़लस

1
@ स्टीफनचेलजैस संभवतः इस तरह से कुछ को लागू करने का एकमात्र तरीका है, आउटपुट को संग्रहीत करने की आवश्यकता है जबकि कमांड चल रहा है जब उसे इसकी आवश्यकता होती है।
Centimane

11
### do this bit once at the top of your script
divert=
exec 3<>"${divert:=$(mktmp)}" 4<>/dev/null
rm -- "$divert"; unset divert
### then do this bit as often as needed
command >&3 2>&3
cat <&3 >&"$(((RTN=$?)?2:4))"

शायद यही करना चाहिए। यह प्रत्येक की आउटपुट को commandहटाए गए अस्थायी फ़ाइल में बफर कर देगा , और उसके बाद /dev/nullया तो इसके आउटपुट को साइपर में या उसके आधार पर साइप्रॉन करेगा या नहीं, इसकी रिटर्न स्थिति शून्य नहीं थी। क्योंकि अस्थायी फ़ाइल को समय से पहले हटा दिया जाता है, इसे किसी भी प्रक्रिया द्वारा नहीं पढ़ा जा सकता है, लेकिन इसकी शेल डिस्क्रिप्टर ( /proc/$pid/fdउपयुक्त अनुमतियों के साथ चुपके स्क्रिप्स को छोड़कर ) पर वर्तमान शेल और उसके बच्चों को पढ़ने की आवश्यकता नहीं है, और जब आप इसके माध्यम से सफाई की आवश्यकता नहीं होती है।

शायद लिनक्स सिस्टम पर अधिक सुविधाजनक समाधान:

divert(){
    "$@" >&3 2>&3 ||
    eval "cat <&3
          return $?"
}   3<<"" 3<>/dev/fd/3

... जो, अधिकांश गोले में, दूसरे की तरह बहुत काम करता है, सिवाय इसके कि आप इसे कॉल कर सकते हैं जैसे divert some simple-command with args:। में उच्च उत्पादन आदेशों से सावधान रहें "$@", हालांकि के लिए dash, yashया कुछ अन्य गोले जो पाइप के साथ यहां-दस्तावेजों करते हैं - मैं यह पाइप बफर को भरने के लिए उन के गोले में संभव हो सकता है लगता है (Linuxes पर चारों ओर 128kb का एक डिफ़ॉल्ट पर) और इतने गतिरोध । यही कारण है कि के लिए एक चिंता नहीं होना चाहिए ksh, mksh, bash, zsh, या बॉर्न शैल, हालांकि - मैं स्पष्ट रूप से ऊपर किया है उन सभी मूल रूप से एक ही बात करते हैं exec


9

आम तौर पर त्रुटि के मामले में कमांड संदेशों को stderrआपके लिए कार्य के लिए आउटपुट करता है जिससे आप सिर्फ सुपरप्रेस कर सकते हैंstdout

mycommand > /dev/null


धन्यवाद, लेकिन जैसा कि मैंने सवाल में कहा था कि मेरे आदेश सभी आउटपुट को लॉग ऑन करते हैं stderr(इसलिए इसका कोई प्रभाव नहीं है)।
मैथ्यू नेपोली

4

अपने स्वयं के जीर्ण बनाने के लिए

my_chronic() {
  tmp=$(mktemp) || return # this will be the temp file w/ the output
  "$@"  > "$tmp" 2>&1 # this should run the command, respecting all arguments
  ret=$?
  [ "$ret" -eq 0 ] || cat "$tmp"  # if $? (the return of the last run command) is not zero, cat the temp file
  rm -f "$tmp"
  return "$ret" # return the exit status of the command
}

3

मैं अपने मेकफाइल्स में कुछ ऐसा करता हूं:

if (mycommand) &> mycommand.log; then 
  echo success 
else 
  c=$?; 
  echo;echo -e "Bad result from previous command, see mycommand.log for more details";echo;
  command_to_run_on_fail
  (exit $c)
fi

अपनी स्थिति के अनुसार, आप इस तरह से कुछ कर सकते हैं:

if ! (mycommand) &> mycommand.log; then 
  c=$?; 
  cat mycommand.log
  rm mycommand.log
  (exit $c)
fi

तो, "if" कमांड चलाता है और आउटपुट को mycommand.log पर पाइप करता है। यदि आपको stdout बनाम stdout बनाम को पकड़ने की आवश्यकता है, तो आपको पाइप कमांड को '&>' से '>' में बदलने की आवश्यकता हो सकती है। यदि कमांड विफल हो जाता है, तो त्रुटि कोड कैप्चर करें, mycommand.log की सामग्री का प्रिंट आउट करें, mycommand.log को निकालें, और अंत में मूल त्रुटि कोड के साथ वापस लौटें।

बिना (बाहर निकलें $ c) आप बाहर निकलने वाले कोड के साथ लौटेंगे जो 'rm' कमांड से मेल खाता है।

अंत में, यदि आप एक लाइनर चाहते हैं, तो ऐसा कुछ काम करेगा।

mycommand &> mycommand.log || cat mycommand.log; rm mycommand.log

2
क्या आप वास्तव में अपने आदेशों / आदि को लपेटते हैं। में (...)इस तरह? क्योंकि यह आपके लिए उपयोगी कुछ भी नहीं करता है, लेकिन अतिरिक्त उप-गोले फैला देता है।
इटन रीसनर

@EtanReisner (exit $c)सेटिंग कर रहा है $?, जो कि आप अन्यथा नहीं कर सकते। if ! (mycommand) &>xयदि पुनर्निर्देशन के साथ सार्थक है यदि कमांड उदाहरण का उपयोग करता है timeया शेल त्रुटि देगा।
माइकल होमर

@ मिचेलहोमर - उन चीज़ों के { ; }लिए परदा है ... हालाँकि exitथोड़ा मुश्किल है, वहाँ।
mikeserv

मेकफाइल स्निपेट में यदि आप पहले से सहेजे गए के साथ बाहर निकलने की कोशिश कर रहे हैं $?तो आप बस उपयोग कर सकते हैं exit $cलेकिन हां, अन्य मामलों (exit $?)में मूल्य है (हालांकि एक शेल फ़ंक्शन rret() { return $1; }सामान्य रूप से बेहतर होगा जो मैं बहस करूंगा)। कमांड के लिए उपखंड अभी भी वास्तव में यद्यपि mikeserv संकेत के रूप में नहीं है।
इटन रीसनर

3

मैं सिर्फ यह बहुत सरल जवाब मिल गया यह अन्य प्रश्न :

output=`mycommand 2>&1` || echo $output

एक जादू की तरह काम करता है!


नोट: मेरे उपयोग के मामले के लिए यह एक बहुत ही सरल समाधान था (सभी CI सर्वरों पर अतिरिक्त सामान स्थापित करने से बचें) इसलिए मैंने इसे स्वीकार करने के लिए चुना। YMMV।
Matthieu Napoli

ध्यान दें कि यदि आप अपने शेल स्क्रिप्ट में सेट-ओ xtrace का उपयोग करते हैं तो सभी आउटपुट फिर से असाइनमेंट आउटपुट के विवरण को लॉग करने के भाग के रूप में होंगे = ... :-)। उस मामले में यह संभव है कि पुरानी का उपयोग करें।
Jan-Philip Gehrcke
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.