यदि इसका एक भाग विफल हो जाता है तो शेल स्क्रिप्ट से बाहर कैसे निकलें?


51

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

n=0
until [ $n -ge 5 ]
do
  gksu *command* && break
  n=$[$n+1]
  sleep 3

जवाबों:


88

एक तरीका यह होगा कि आप set -eअपनी स्क्रिप्ट की शुरुआत में शामिल हों। इसका मतलब है कि (से help set):

  -e  Exit immediately if a command exits with a non-zero status.

इसलिए यदि आपकी कोई भी कमांड विफल हो जाती है, तो स्क्रिप्ट बाहर निकल जाएगी।

वैकल्पिक रूप से, आप exitसंभावित विफलता बिंदुओं पर स्पष्ट विवरण जोड़ सकते हैं :

command || exit 1

5
मैं और बैश विकी ) लोगों को उचित त्रुटि से निपटने में कुछ सोच डालते हैं बजाय इसके कि वे (आईएमओ द्वारा डिजाइन किए गए) टूटे हुए set -eफ़ीचर का उपयोग करें। हालांकि यह वास्तव में यहाँ लागू नहीं होता है। ओपी कमांड चलाने के 5 असफल प्रयासों के बाद स्क्रिप्ट से बाहर निकलना चाहता है।
स्टीफन चेजलस

1
@ StéphaneChazelas मैं आपसे इस बारे में बहस नहीं करूंगा कि क्या यह टूट गया है, मुझे यकीन है कि आप सही हैं। हालांकि, ओपी ने पूछा "मैं कैसे एक शेल स्क्रिप्ट लिख सकता हूं जो बाहर निकलता है, अगर इसका एक हिस्सा विफल हो जाता है?", तो आपको क्या लगता है कि यह 5 विफलताओं के बाद बाहर निकलने के बारे में है?
terdon

क्योंकि मैं किसी अन्य तरीके के बारे में नहीं सोच सकता, जिस पर प्रश्न की व्याख्या की जा सकती है।
स्टीफन चेजलस

1
@ स्टीफेनचैलेज आप अच्छी तरह से सही हो सकते हैं। मैंने इसकी शाब्दिक व्याख्या की: यदि इसके किसी भी भाग में विफल होने पर पूरी स्क्रिप्ट कैसे बाहर निकल सकती है। और set -eऐसा करने का एकमात्र तरीका मुझे पता है।
terdon

उस लिपि के स्निपेट में, जो कमांड्स ट्रिगर हो सकते हैं set -e, sleep( breakएक विशेष बिल्डिन होने के कारण स्क्रिप्ट अधिकांश शेल में विफलता पर बाहर निकलने का कारण बन सकती है, ifया उसके बाईं ओर स्थित कमांड &&इससे प्रभावित नहीं होते हैं set -e, n=...विफल हो सकता है अगर nकेवल-पढ़ने के लिए है, लेकिन तब यह स्क्रिप्ट के बिना भी बाहर निकल जाएगा set -e), ताकि व्याख्या काफी संभावना न लगे। मैं सहमत हूं कि प्रश्न खराब शब्द है।
स्टीफन चेज़लस

17

आप कीवर्ड का उपयोग करके किसी भी स्थान पर स्क्रिप्ट से बाहर निकल सकते हैं exit। आप अन्य प्रोग्राम्स को इंगित करने के लिए एक एक्जिट कोड भी निर्दिष्ट कर सकते हैं कि आपकी स्क्रिप्ट कैसे विफल हुई, जैसे exit 1या exit 2इत्यादि (कन्वेंशन से, एक्जिट कोड 0 सफलता के लिए है और 0 से अधिक कुछ भी विफलता को दर्शाता है; हालाँकि, कन्वेंशन द्वारा भी, बाहर निकलें 127 से ऊपर के कोड असामान्य समाप्ति (जैसे एक संकेत द्वारा) के लिए आरक्षित हैं।

विफलता पर बाहर निकलने के लिए सामान्य निर्माण है

if [ failure condition ]; then
    exit n
fi

उपयुक्त के साथ failure conditionऔर n। लेकिन विशिष्ट परिदृश्यों में आप अलग तरीके से आगे बढ़ सकते हैं। अब आपके मामले के लिए मैं आपके प्रश्न की व्याख्या करता हूं कि यदि gksuअसफल होने के पांच में से कोई भी चालान है , तो आप बाहर निकलने का मतलब है। एक तरीका इस तरह से एक फ़ंक्शन का उपयोग करना है

function try_command {
    for i in 1 2 3 4 5 ; do
        if gksu command ; then
            return 0
        fi
    fi
    exit 1
}

और फिर, द्वारा लूप को इनवॉइस करें try_command

आपके प्रश्न को कैसे संबोधित किया जाए, इसके (अधिक) उन्नत या परिष्कृत तरीके हैं। हालांकि, स्टीफन के समाधान की तुलना में ऊपर का समाधान शुरुआती लोगों के लिए अधिक सुलभ है।


10
attempt=0
until gksu command; do
  attempt=$((attempt + 1))
  if [ "$attempt" -gt 5 ]; then
    exit 1
  fi
done

exitस्क्रिप्ट को तब तक बाहर निकालता है जब तक कि उसे सब-उपलक्ष्य में नहीं बुलाया जाता। यदि स्क्रिप्ट का वह भाग उप-प्रकार में है, उदाहरण के लिए क्योंकि यह पाइप-लाइन के भीतर (...)या $(...)उसके हिस्से में है, तो यह केवल उस उप -सीमा से बाहर निकल जाएगा ।

उस स्थिति में, यदि आप चाहते हैं कि स्क्रिप्ट सबस्क्रिप्शन के अतिरिक्त बाहर निकले, तो आपको exitउस सब-टाइप से बाहर निकलने के लिए कॉल करना होगा ।

उदाहरण के लिए, यहां उप-स्तरों के 2 नेस्टेड स्तर हैं:

(
  life=hard
  output=$(
    echo blah
    [ "$life" = easy ] || exit 1 # exit subshell
    echo blih not run
  ) || exit # if the subshell exits with a non-zero exit status,
            # exit as well with the same exit status

  echo not run either
) || exit # if the subshell exits with a non-zero exit status,
          # exit as well with the same exit status

यह पेचीदा हो सकता है यदि उपधारा एक पाइपलाइन का हिस्सा है। bashएक विशेष है $PIPESTATUSसरणी, के लिए इसी तरह zshके $pipestatusएक है कि तुम यहाँ मदद कर सकते हैं:

{
   echo foo
   exit 1
   echo bar
} | wc -c
subshell_ret=${PIPESTATUS[0]}
if [ "$subshell_ret" -ne 0 ]; then
  exit "$subshell_ret"
fi

3

ट्रैप सिग्नल मिलने पर कार्रवाई करेगा।

trap "echo EXIT;  exit" 0
trap "echo HUP;   exit" 1
trap "echo CTL-C; exit" 2
trap "echo QUIT;  exit" 3
trap "echo ERR;   exit" ERR
n=0
until [ $n -ge 5 ]
do
  n=$[$n+1]
  echo $n
  sleep 3
done

इसे चलाएं और इसे सामान्य रूप से बाहर निकलने दें। यह सिग्नल 0 पर फंस जाता है।

EXIT

इसे फिर से चलाएं और ^ C के साथ बाधित करें। यह सिग्नल 2 और सिग्नल 0 दोनों पर फँस जाता है।

CTL-C
EXIT

एक गैर-शून्य निकास स्थिति ईआरआर पर फंस जाएगी

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