क्या एक बैश फ़ंक्शन लिखने का एक तरीका है जो पूरे निष्पादन को निरस्त करता है, कोई फर्क नहीं पड़ता कि इसे कैसे कहा जाता है?


83

मैं पूरी पटकथा को समाप्त करने के लिए अपने बैश कार्यों में "निकास 1" कथन का उपयोग कर रहा था और यह ठीक काम कर रहा था:

function func()
{
   echo "Goodbye"
   exit 1
}
echo "Function call will abort"
func
echo "This will never be printed"

लेकिन तब मुझे एहसास हुआ कि जब यह कहा जाता है तो यह काम नहीं करता है:

res=$(func)

मैं समझता हूं कि मैंने एक सबशेल और "एग्जिट 1" एबॉर्ट्स बनाया है जो सबमिशन और प्राइमरी एक नहीं है ...।

लेकिन क्या एक फ़ंक्शन लिखने का एक तरीका है जो पूरे निष्पादन को निरस्त करता है, कोई फर्क नहीं पड़ता कि इसे कैसे कहा जाता है? मुझे बस असली रिटर्न वैल्यू (फंक्शन द्वारा प्रतिध्वनित) प्राप्त करने की आवश्यकता है।

जवाबों:


90

आप क्या कर सकते हैं, TERMसिग्नल से बाहर निकलने के लिए शीर्ष स्तर का शेल रजिस्टर करें , और फिर TERMटॉप लेवल शेल को भेजें :

#!/bin/bash
trap "exit 1" TERM
export TOP_PID=$$

function func()
{
   echo "Goodbye"
   kill -s TERM $TOP_PID
}

echo "Function call will abort"
echo $(func)
echo "This will never be printed"

इसलिए, आपका फ़ंक्शन TERMशीर्ष स्तर के शेल में एक सिग्नल वापस भेजता है , जो कि प्रदान की गई कमांड का उपयोग करके पकड़ा जाता है और इस मामले में "exit 1",।


1
मैं सी setsid()फ़ंक्शन के बारे में सोच रहा था , लेकिन यह उसी तरह से काम नहीं करता है। setsidकमांड का उपयोग नहीं करने के लिए अपडेट किया गया , क्योंकि इसके लिए हमें एक नई प्रक्रिया शुरू करनी होगी।
फेटलएयर

3
काम करता है। फंक्शन नेस्टिंग का कोई भी लेवल, कोई भी फ्लो ... बस काम करता है।
18

यह इस से बाहर एक सामान्य बीच में बंद करें () फ़ंक्शन बनाने के लिए है कि पहली बहस के कोड का उपयोग कर, जैसे बाहर निकलता है संभव है abort 2करना होगा trap "exit 2" TERMसे पहले kill?
नील सी। ओब्राम्स्की

@ NeilC.Obremski: ज़रूर। यह मुख्य रूप से शीर्ष स्तर के शेल में वापस प्रचार करने के लिए मूल्य प्राप्त करने का एक मुद्दा है। संभवतः एक कमांड का उपयोग tempfileकरें जैसे कि शीर्ष शेल में कोड को स्टोर करने के लिए एक जगह का चयन करें, फिर शेल है जो उस फ़ाइल में कोड लिखने से बाहर निकल रहा है, तो बस माता-पिता के हैंडलर में पढ़ें।
FatalError

2
लगता है जब काम कर रहे हैं उपखंड नहीं हैं। set -E यहाँ
रॉन बर्क

42

आप उपयोग कर सकते हैं set -eजो बाहर निकलता है, तो एक गैर शून्य स्थिति के साथ एक आदेश बाहर निकलता है :

set -e 
func
set +e

या रिटर्न मान को पकड़ो:

(func) || exit $?

3
दिलचस्प है कि मैं एक समाधान देखता हूं। मुख्य स्क्रिप्ट में "सेट-ई" किसी भी फ़ंक्शन को 1 (या इसके साथ बाहर निकलने) को पूरा निष्पादन रद्द करने का कारण बनता है। दुर्भाग्य से "सेट-ई" काफी सारे व्यवहार को बदल देता है और मैं इसका उपयोग नहीं कर सकता।
LiMar

1
आपको संख्यात्मक तुलना के लिए (()) का उपयोग करना चाहिए। अंदर [] -gt, -eq, आदि का उपयोग किया जाना चाहिए।
जोर्डम

16
या यहां तक ​​किres=$(func) || exit
ग्लेन जैकमैन

@glennjackman को कुकी मिलती है, मुझे लगता है। यह बहुत साफ है कि मेरे पास कचरा है!
ब्राइस

3
इस तरह के सवाल की भावना को धता बताती है। यदि प्रत्येक फ़ंक्शन कॉल को स्वयं त्रुटि को पकड़ने की आवश्यकता है, exit तो पहली जगह में उपयोग करने का कोई मतलब नहीं है। समारोह बस वापस आ सकता है। / हालांकि, अगर set -eइसे विश्व स्तर पर सेट किया जाता है , तो इससे अच्छी समझ होती है
phil294

2

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

function child() {
    local parent_pid="$1"
    local other="$2"
    ...
    if [[ $failed ]]; then
        kill -QUIT "$parent_pid"
    fi
}

2

मुझे लगता है कि बेहतर है

#!/bin/bash
set -e
trap "exit 1" ERR

myfunc() {
     set -x # OPTIONAL TO SHOW ERROR
     echo "Exit with failure"
     set +x # OPTIONAL
     exit 1
}
echo "BEFORE..."
myvar="$(myfunc)"
echo "AFTER..But not shown"

0

लेकिन क्या एक फ़ंक्शन लिखने का एक तरीका है जो पूरे निष्पादन को निरस्त करता है, कोई फर्क नहीं पड़ता कि इसे कैसे कहा जाता है?

नहीं।

मुझे बस असली रिटर्न वैल्यू (फंक्शन द्वारा प्रतिध्वनित) प्राप्त करने की आवश्यकता है।

आप ऐसा कर सकते हैं

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