कैसे एक बयान का उपयोग कर बाहर निकलने की स्थिति की जांच करने के लिए


255

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

मैं इसके होने के बारे में सोच रहा हूं

if [ $? -eq 1 ]
then
   echo "blah blah blah"
fi

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


3
पट्टिका आपकी पूरी स्क्रिप्ट (या कम से कम एक व्यापक गुंजाइश) पोस्ट करती है। और यह ठीक लगता है।
रेडएक्स

5
यदि आपको दो अलग-अलग स्थानों में कुछ विशेष कार्यक्रम आह्वान से निकास कोड का उपयोग करने की आवश्यकता है, तो आपको इसे संरक्षित करने की आवश्यकता है - कुछ की तर्ज परsome_program; rc=$?; if [ ${rc} -eq 1 ] .... fi ; exit ${rc}
twalberg

जवाबों:


262

हर कमांड जो चलता है उसकी एग्जिट स्टेटस होती है।

यह जाँच उस कमांड की निकास स्थिति को देख रही है जो उस पंक्ति के चलने से पहले हाल ही में समाप्त हुई थी।

यदि आप चाहते हैं कि जब परीक्षण सही हो (पिछली कमांड विफल रही) तो आप अपनी स्क्रिप्ट से बाहर निकलें, तो आप exit 1उस के ifबाद उस ब्लॉक के अंदर (या जो भी) डालते हैं echo

यह कहा जा रहा है कि यदि आप कमांड चला रहे हैं और निम्नलिखित का उपयोग करके इसके आउटपुट का परीक्षण करना चाहते हैं, तो यह अक्सर अधिक सीधा होता है।

if some_command; then
    echo command returned true
else
    echo command returned some error
fi

या कि !नकारात्मक के लिए उपयोग के चारों ओर मोड़ करने के लिए

if ! some_command; then
    echo command returned some error
else
    echo command returned true
fi

ध्यान दें कि न तो उन लोगों को परवाह है कि त्रुटि कोड क्या है। यदि आप जानते हैं कि आपको केवल एक विशिष्ट त्रुटि कोड की परवाह है तो आपको $?मैन्युअल रूप से जांच करने की आवश्यकता है ।


11
@ डेडसेल 4 जब किसी प्रोग्राम की विफलता पर एक शेल स्क्रिप्ट को समाप्त करने की आवश्यकता होती है, तो निम्नलिखित मुहावरा उपयोगी होता हैa_command || return 1
gboffi

10
@gboffi returnकेवल एक फंक्शन और एक सोर्सेड स्क्रिप्ट में काम करता है। आपको exitअन्य मामले की आवश्यकता है (जो एक फ़ंक्शन और एक खटारा स्क्रिप्ट में बहुत अधिक करता है)। लेकिन हाँ, यह निश्चित रूप से एक उचित पैटर्न है यदि आपको किसी विशिष्ट सफाई या अतिरिक्त आउटपुट की आवश्यकता नहीं है।
इटन रिस्नर

1
मेरा कहना है कि dash, कई आधुनिक लिनक्स वितरणों में डिफ़ॉल्ट गैर-संवादात्मक शेल, निष्पादित शैल स्क्रिप्ट के बीच returnऔर exitअंदर के भेद का ध्यान नहीं रखते हैं। dashअगर मैं इसमें उपयोग करता हूं तो भी स्क्रिप्ट से बाहर निकलता हूं return
गॉबोफी

पिछले दो चेक के पीछे क्या तर्क है? ऐसा लगता है कि if <command>बाहर निकलने का कोड होने पर यह स्थिति सहज हो जाती है। किसी भी अन्य भाषा में यह दूसरा तरीका होगा
sjw

3
महत्वपूर्ण नोट: यह पाइप के लिए काम नहीं करेगा। if ! some_command | some_other_commandकुछ_कमांड की स्थिति को अनदेखा करेगा। दो सबसे अधिक कमांड वर्कअराउंड set -o pipefail(आपके प्रोग्राम के अन्य हिस्सों में कार्यक्षमता बदल सकते हैं) या ifस्टेटमेंट को if [[ ${PIPESTATUS[0]} -ne 0 ]]एक अलग फॉलो-अप कमांड (बदसूरत, लेकिन कार्यात्मक) के रूप में स्थानांतरित करने के लिए हैं । यदि आप उपयोग कर रहे हैं, set -eतो आप || trueपाइप के अंत में भी जोड़ना चाहेंगे जब दूसरे समाधान का उपयोग करते समय पाइप को नियंत्रण प्रवाह से हटा दिया जाए ifअन्यथा यह तुरंत बाहर निकल जाएगा।
एलेक्स जाॅनसन

186

ध्यान दें कि बाहर निकलने के कोड! = 0 का उपयोग त्रुटि रिपोर्ट करने के लिए किया जाता है। तो, यह करना बेहतर है:

retVal=$?
if [ $retVal -ne 0 ]; then
    echo "Error"
fi
exit $retVal

के बजाय

# will fail for error codes > 1
retVal=$?
if [ $retVal -eq 1 ]; then
    echo "Error"
fi
exit $retVal

आपको रिटेल पर परीक्षण करना चाहिए, क्योंकि $? RetVal के असाइनमेंट के बाद आपकी कमांड से रिटर्न वैल्यू नहीं है।
ar78

वास्तव में नहीं: mywiki.wooledge.org/BashFAQ/002 - हालांकि, मैं मानता हूं कि संपादित करने से पठनीयता में सुधार होता है।
Oo.oO

1
बस यह पोस्ट पाया गया कि यह बताते हैं stackoverflow.com/questions/20157938/…
ar78

dnf check-updateरिटर्न 0 (कोई अपडेट नहीं), 100 (अपडेट उपलब्ध) या 1 (त्रुटि)।
jww

1
@jww - ठीक है, यह कन्वेंशन ( gnu.org/software/bash/manual/html_node/Exit-Status.html ) के खिलाफ जाने के लिए एक अच्छा विचार नहीं है । लेकिन, ठीक है, इसे रोकने के लिए कुछ भी नहीं है। यदि dnfडेवलपर्स ने इस तरह से चुना है, तो यह उनकी पसंद है। लेकिन फिर भी, उनकी पसंद टूटने के लिए विनिर्देश नहीं बनाती है :)
Oo.oO

44

$?किसी भी अन्य की तरह एक पैरामीटर है। आप अंततः कॉल करने से पहले उपयोग करने के लिए इसके मूल्य को बचा सकते हैं exit

exit_status=$?
if [ $exit_status -eq 1 ]; then
    echo "blah blah blah"
fi
exit $exit_status

29

स्पष्ट ifकथन के लिए वैकल्पिक

न्यूनतम:

test $? -eq 0 || echo "something bad happened"

पूर्ण:

EXITCODE=$?
test $EXITCODE -eq 0 && echo "something good happened" || echo "something bad happened"; 
exit $EXITCODE

13

बस सहायक और विस्तृत जवाब में जोड़ने के लिए :

यदि आपको निकास कोड को स्पष्ट रूप से जांचना है, तो अंकगणितीय ऑपरेटर का उपयोग करना बेहतर है (( ... )), इस तरह से:

run_some_command
(($? != 0)) && { printf '%s\n' "Command exited with non-zero"; exit 1; }

या, एक caseकथन का उपयोग करें :

run_some_command; ec=$?  # grab the exit code into a variable so that it can
                         # be reused later, without the fear of being overwritten
case $ec in
    0) ;;
    1) printf '%s\n' "Command exited with non-zero"; exit 1;;
    *) do_something_else;;
esac

बाश में त्रुटि से निपटने के बारे में संबंधित उत्तर:

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