एक खोल से बाहर निकलें खोल स्क्रिप्ट


30

इस स्निपेट पर विचार करें:

stop () {
    echo "${1}" 1>&2
    exit 1
}

func () {
    if false; then
        echo "foo"
    else
        stop "something went wrong"
    fi
}

आम तौर पर जब funcइसे कहा जाता है तो यह स्क्रिप्ट को समाप्त करने का कारण होगा, जो कि इच्छित व्यवहार है। हालाँकि, यदि इसे एक सब-शेल में निष्पादित किया जाता है, जैसे कि

result=`func`

यह स्क्रिप्ट से बाहर नहीं निकलेगा। इसका मतलब है कि कॉलिंग कोड को हर बार फ़ंक्शन की निकास स्थिति की जांच करनी होगी। इससे बचने का कोई रास्ता है क्या? क्या यह किसलिए set -eहै?


1
मैं एक फ़ंक्शन "स्टॉप" चाहता हूं जो संदेश को stderr पर प्रिंट करता है और स्क्रिप्ट को रोकता है, लेकिन यह तब नहीं रुकता है जब कॉल रोकने वाला फ़ंक्शन उप-शेल में निष्पादित होता है, जैसे उदाहरण में
अर्नेस्ट एसी

2
बेशक, क्योंकि यह उपधारा से बाहर निकलता है वर्तमान में नहीं। सीधे फ़ंक्शन को कॉल करें func:।

1
मैं इसे सीधे नहीं कह सकता क्योंकि यह एक स्ट्रिंग देता है जिसे एक चर में संग्रहीत किया जाना है
अर्नेस्ट एसी

1
@ErnestAC मूल प्रश्न में सभी विवरण प्रदान करें। उपरोक्त फ़ंक्शन एक स्ट्रिंग वापस नहीं करता है।

1
@ मैं उदाहरण बदल गया
अर्नेस्ट एसी

जवाबों:


10

आप कॉल करने से पहले मूल शेल ( ) को मार सकते हैं , और यह शायद काम करेगा। परंतु:kill $$exit

  • यह मेरे लिए बदसूरत लगता है
  • यह टूट जाएगा यदि आपके पास वहां दूसरा उप-समूह है, अर्थात, उप-उप के अंदर एक उप-भाग का उपयोग करें।

इसके बजाय, आप बैश FAQ में मान वापस करने के लिए कई तरीकों में से एक का उपयोग कर सकते हैं । उनमें से ज्यादातर दुर्भाग्यवश इतने महान नहीं हैं। आप प्रत्येक फ़ंक्शन कॉल के बाद त्रुटियों के लिए जाँच कर सकते हैं ( -eबहुत सारी समस्याएं हैं )। या तो, या पर्ल पर स्विच करें।


5
धन्यवाद। मैं हालांकि अजगर पर स्विच करूँगा, हालाँकि।
अर्नेस्ट एसी

2
जैसा कि मैंने लिखा है, यह वर्ष 2019 है। किसी को "पर्ल पर स्विच करने" के लिए कहना हास्यास्पद है। विवादास्पद होने के लिए क्षमा करें, लेकिन क्या आप किसी को 'C' से निराश होकर कोबोल में जाने के लिए कहेंगे, जो IMO के बराबर है? जैसा कि अर्नेस्ट बताते हैं, पायथन बेहतर विकल्प है। मेरी प्राथमिकता रूबी होगी। किसी भी तरह, कुछ भी लेकिन पर्ल।
ग्राहम निकोल्स

38

आप यह तय कर सकते हैं कि उदाहरण के लिए बाहर निकलने की स्थिति 77 का अर्थ है किसी भी स्तर के उप-स्तर से बाहर निकलें, और करें

set -E
trap '[ "$?" -ne 77 ] || exit 77' ERR

(
  echo here
  (
    echo there
    (
      exit 12 # not 77, exit only this subshell
    )
    echo ici
    exit 77 # exit all subshells
  )
  echo not here
)
echo not here either

set -EERRजाल के साथ संयोजन में एक बेहतर संस्करण की तरह set -eहै कि यह आपको अपनी त्रुटि से निपटने की अनुमति देता है।

Zsh में, ईआरआर ट्रैप्स अपने आप विरासत में मिलते हैं, इसलिए आपको ज़रूरत नहीं है set -E, आप ट्रैप को TRAPERR()फ़ंक्शंस के रूप में भी परिभाषित कर सकते हैं , और इसके माध्यम से संशोधित कर सकते हैं $functions[TRAPERR], जैसेfunctions[TRAPERR]="echo was here; $functions[TRAPERR]"


1
दिलचस्प समाधान! से अधिक स्पष्ट रूप से सुरुचिपूर्ण kill $$

3
देखने के लिए एक बात, यह जाल प्रक्षेपित आदेशों को नहीं संभालेगा, उदाहरण के लिए echo "$(exit 77)"; स्क्रिप्ट तब तक echo ""
चलेगी

Interresting! वहाँ (बहुत पुराने) पर कोई भाग्य है कि -E नहीं है? शायद हमें USER सिग्नल पर एक जाल को परिभाषित करने और उस सिग्नल को मारने का उपयोग करना होगा? मैं कुछ खोज भी करूंगा ...
ओलिवियर दुलक

77 के बजाय 1 वापस करने के लिए, उप-शेल जाल में नहीं होने पर कैसे पता करें?
छत

7

के विकल्प के रूप में kill $$, आप भी कोशिश कर सकते हैं kill 0, यह नेस्टेड सबहेल के मामले में काम करेगा (सभी कॉलर्स और साइड प्रोसेस को सिग्नल प्राप्त होगा) ... लेकिन यह अभी भी क्रूर और बदसूरत है।


2
क्या यह प्रक्रिया आईडी 0 नहीं मारेंगे?
अर्नेस्ट एसी

5
वह पूरी प्रक्रिया समूह को मार डालेगा। आप उन चीजों को हिट कर सकते हैं जो आप नहीं चाहते हैं (उदाहरण के लिए आपने पृष्ठभूमि में कुछ चीजें शुरू की हैं)।
derobert

2
@ErnestAC मार (2) मैनपेज देखें, pids have0 का विशेष अर्थ है।
derobert

0

इसे इस्तेमाल करे ...

stop () {
    echo "${1}" 1>&2
    exit 1
}

func () {
    if $1; then
        echo "foo"
    else
        stop "something went wrong"
    fi
}

echo "shell..."
func $1

echo "subshell..."
result=`func $1`

echo "shell..."
echo "result=$result"

मुझे मिलने वाले परिणाम हैं ...

# test_exitsubshell true
shell...
foo
subshell...
shell...
result=foo
# test_exitsubshell false
shell...
something went wrong

टिप्पणियाँ

  • ifपरीक्षण करने की अनुमति देने के लिए परिमाणित trueया false(2 रन देखें)
  • जब ifपरीक्षा होती है false, तो हम कभी भी उपधारा तक नहीं पहुँचते हैं।

यह उस मूल विचार के समान है जो उपयोगकर्ता पोस्ट कर रहा था और कहा था कि यह काम नहीं कर रहा है। मुझे नहीं लगता कि यह सब-केस के लिए काम करता है। "शेल" मामले के बाद आपका परीक्षण गलत एग्जिट का उपयोग करता है और कभी भी "सब्स्क्रिप्शन" टेस्ट केस में नहीं जाता है। मेरा मानना ​​है कि यह उस मामले के लिए विफल होगा क्योंकि सबस्क्रिप्शन "एग्जिट 1" कॉल से बाहर निकल जाएगा लेकिन बाहरी शेल में त्रुटि का प्रचार नहीं करता है।
अटक गया

0

(बैश विशिष्ट उत्तर) बैश में अपवादों की कोई अवधारणा नहीं है। हालाँकि, सेट -o एरेक्सिट के साथ (या समतुल्य: सेट-ई) बाहरी स्तर पर, विफल कमांड के परिणामस्वरूप गैर-शून्य निकास स्थिति के साथ सब-एक्ज़िट का परिणाम होगा। यदि यह उन उपधाराओं के निष्पादन के चारों ओर सशर्त बिना नेस्टेड उप-श्रेणियों का एक सेट है, तो यह पूरी स्क्रिप्ट और निकास को प्रभावी रूप से 'रोल अप' करेगा।

यह एक बड़ा स्क्रिप्ट में विभिन्न बैश कोड के बिट्स को शामिल करने की कोशिश करते समय मुश्किल हो सकता है। बैश का एक हिस्सा अपने आप ही ठीक काम कर सकता है, लेकिन जब एरेक्सिट (या एरेक्सिट के बिना) के तहत निष्पादित किया जाता है, तो अप्रत्याशित तरीके से व्यवहार करें।

[१ ९ २.१६5.१३.१६ (f0f5e19e) ~ २२:५.1:२२] # बैश-इरोइक्सिट / tmp / foo
कुछ गलत हो गया
[192.168.13.16 (f0f5e19e) ~ 22:58:31] # बैश / tmp / पूजा
कुछ गलत हो गया
लेकिन हमें यहाँ वैसे भी मिला
[192.168.13.16 (f0f5e19e) ~ 22:58:37] # बिल्ली / tmp / फू
#! / Bin / bash
रुकें () {
    गूंज "$ {1}"
    बाहर निकलें 1
}

अगर झूठ है; फिर
    इको "फू"
अन्य
    (
        बंद करो "कुछ गलत हो गया"
    )
    गूंज "लेकिन हम यहाँ वैसे भी"
फाई
[192.168.13.16 (f0f5e19e) ~ 22:58:40] #

-2

एक लाइनर में बाहर निकलने के लिए मेरा उदाहरण:

COMAND || ( echo "ERROR – executing COMAND, exiting..." ; exit 77 );[ "$?" -eq 77 ] && exit

1
यह वास्तव में ऐसा जवाब नहीं लगता है जो ओपी द्वारा अनुरोध किए गए उप-गोले में चल रहे कमांड के साथ काम करेगा ... उन्होंने कहा कि जब तक मैं नीचे दिए गए वोटों से असहमत नहीं होता, तब तक वह जवाब नहीं देता। बिना किसी टिप्पणी या कारण के डाउन वोट बुरे उत्तरों के समान ही अयोग्य हैं।
डीवीएस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.