2012-06-21 11 views
26

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

error() 
{ 
    echo $1 
    exit 1 
} 

fn() 
{ 
    if [ $# == 0 ]; then 
    error "Insufficient parameters." 
    fi 
    # do stuff 
} 

$ fn 
Insufficient parameters. 
[shell terminates] 

तो मेरी सवाल है, मैं वर्तमान खोल समाप्त बिना और एक नया subshell को उत्पन्न करने के बिना समारोह ढेर में सभी कार्यों बाहर निकल सकते हैं?

धन्यवाद

उत्तर

30

खोल से बाहर निकले बिना समारोह ढेर बाहर निकलने के लिए एक आदेश का उपयोग कर सकते हैं हो सकता है:

kill -INT $$ 

pizza के रूप में कहा गया है, इस Ctrl-C दबाने की तरह है, जो मौजूदा स्क्रिप्ट को चलने से रोक देगा और आपको कमांड प्रॉम्प्ट पर छोड़ देगा।

 

 


नोट: एकमात्र कारण मैं चयन नहीं किया pizza के जवाब है, क्योंकि इस उसकी/उसके जवाब में दफनाया गया था और सीधे उत्तर नहीं मिला।

+0

निम्नलिखित "वापसी" बेहतर है ऐसा लगता है: यह इस उद्देश्य के लिए खोल में बनाई गई कार्यक्षमता है। खोल मारना सुरुचिपूर्ण है। – JPGConnolly

+2

@JPGConnolly 'निम्नलिखित "वापसी से आपका क्या मतलब है" यह बेहतर लगता है'? यदि आप बिल्टिन 'रिटर्न' कथन का उपयोग करना चाहते हैं, तो आप इस सवाल को नहीं पढ़ रहे हैं क्योंकि इसका उपयोग करने का कोई आसान तरीका नहीं है कि यह एक फ़ंक्शन के भीतर से बेस खोल पर वापस कूद जाएगा जिसे कई अन्य कार्यों को गहराई से जोड़ा जाता है प्रत्येक फंक्शन कॉल के रिटर्न वैल्यू से पूछताछ करें, जो कुछ मामलों में व्यावहारिक या संभव नहीं है। 'Kill -INT $$ 'करना इस मामले में' वापसी 'का उपयोग करने से काफी अधिक सुरुचिपूर्ण है। – Adrian

+0

$ का मूल्य क्या है? क्या स्रोत फ़ंक्शन का कॉलर देखता है? या यह भी इसे समाप्त करता है? – Michael

2

return कथन का उपयोग, लेकिन आप बुला त्रुटि

+1

फ़ंक्शन कथन की आवश्यकता के बिना कार्य वापस आते हैं। –

+1

लेकिन ओपी चाहता है कि फ़ंक्शन तुरंत समाप्त हो जाए, न कि जब यह फ़ंक्शन बॉडी के नीचे हो जाता है। –

+0

मैं ढेर पर सभी कार्यों को समाप्त करना चाहता हूं। "लेकिन अगर सामान से पहले" मतलब क्या है? – Adrian

1

खोल वास्तव में कई समारोह के माध्यम से रीवाइंड के लिए एक अपवाद प्रणाली नहीं है के बाद वापसी को जोड़ने के लिए एक ही बार में कॉल की जरूरत है। आपको केवल वापसी मूल्यों की जांच करनी होगी और मैन्युअल रूप से नीचे से वापस आना होगा।

+0

का उपयोग किया जा सकता है मैं नीचे रास्ते पर जांच कर रहा हूँ। बस उन सभी कार्यों से बाहर निकलना चाहते हैं जो वर्तमान में खोल से बाहर निकले बिना चल रहे हैं। – Adrian

+1

जिसका अर्थ है कि आप 'निकास' के बजाय 'वापसी' का उपयोग करते हैं। लेकिन मेरा मतलब यह है कि सभी तरह से नीचे यह है कि आपको प्रत्येक समारोह में अलग-अलग 'वापसी' करना है, न कि केवल एक बार में। –

+1

दुर्भाग्यवश यह है कि मैं जो करना चाहता था उसके लिए उपयोगी नहीं है। – Adrian

5

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

वैकल्पिक रूप से आप शेल स्क्रिप्ट के रूप में fn को परिभाषित कर सकते हैं, ताकि exit जो भी आप चाहते हैं (जब तक कि कांटा बहुत महंगा न हो)।

+1

सभी फ़ंक्शन निकास मानों के लिए चेक करना उपयोगी नहीं है। वर्तमान में, इस समस्या को हल करने के लिए, मुझे शेल स्क्रिप्ट के अंदर व्यक्तिगत कार्यों को कॉल किया जा रहा है। इस प्रकार इसे छोड़कर मेरे खोल से बाहर नहीं निकल जाएगा। – Adrian

+0

आपको सभी निकास मूल्यों की जांच करने की आवश्यकता नहीं है - बस जांचें कि यह सफल हुआ है - 'अगर my_function' - या क्या निकास कोड गैर-शून्य है -' my_function; अगर [$? -एक 0] '। – l0b0

+0

फ़ंक्शन को शेल स्क्रिप्ट के रूप में परिभाषित करना एक अच्छा समाधान है, हालांकि उस फ़ंक्शन में "निकास" का उपयोग करके खोल से बाहर निकल जाएगा। आप शेल से बाहर निकले बिना फ़ंक्शन को रोकने के लिए "वापसी" का उपयोग करने में सही हैं। – JPGConnolly

7

आप एक

exit() { return $1;} 

गोले तो

source ./your_script 

संशयवादियों के जवाब में, यह केवल वर्तमान खोल प्रभावित करते हैं, यह प्रभावित नहीं करता है आप अंडे कर सकते हैं।

अधिक सूचनात्मक रूप

exit() { 
    local ans 
    local line 
    read -p "You really want to exit this? " line 
    ans=$(echo $line) 
    case "$ans" in 
      Y);; 
      y);; 
      *)kill -INT $$;; 
    esac 
    unset -f exit 
    exit $1 
} 
+4

छुपा/ओवरराइटिंग बिल्टिन कभी भी एक अच्छा विचार नहीं है। – glglgl

+0

यह मान्य बैश वाक्यविन्यास नहीं है। –

+0

यह वैध वाक्यविन्यास है। – pizza

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

  • कोई संबंधित समस्या नहीं^_^