set -eस्क्रिप्ट को समाप्त करता है यदि कुछ शर्तों के अलावा, नॉनज़रो एग्जिट कोड का सामना करना पड़ता है। कुछ शब्दों में इसके उपयोग के खतरों को समझने के लिए: यह व्यवहार नहीं करता है कि लोग यह कैसे सोचते हैं।
मेरी राय में, इसे एक खतरनाक हैक माना जाना चाहिए जो केवल संगतता उद्देश्यों के लिए मौजूद है। यह set -eकथन उस भाषा से शेल को चालू नहीं करता है जो त्रुटि कोड का उपयोग ऐसी भाषा में करता है जो अपवाद जैसे नियंत्रण प्रवाह का उपयोग करता है, यह केवल उस व्यवहार का अनुकरण करने का खराब प्रयास करता है।
ग्रेग वूलेज के खतरों पर बहुत कुछ कहना है set -e:
दूसरे लिंक में, के अनपेक्षित और अप्रत्याशित व्यवहार के विभिन्न उदाहरण हैं set -e।
के अनपेक्षित व्यवहार के कुछ उदाहरण set -e(कुछ उपरोक्त विकि लिंक से लिया गया है):
सेट
x = 0
चलो x ++
इको "x $ x" है
उपरोक्त शेल स्क्रिप्ट समय से पहले बाहर निकलने का कारण बनेगा, क्योंकि let x++रिटर्न 0, जिसे letकीवर्ड द्वारा एक गलत मान के रूप में माना जाता है और एक नॉनजेरो एग्जिट कोड में बदल जाता है। set -eयह नोटिस, और चुपचाप स्क्रिप्ट को समाप्त करता है।
सेट
[-d / opt / foo] && इको "चेतावनी: फू पहले से स्थापित है। अधिलेखित हो जाएगा।" > और 2
गूंज "संस्थापन फू ..."
उपरोक्त कार्य /opt/fooपहले से मौजूद होने पर, चेतावनी को छापते हुए काम करता है।
सेट
check_prepret_install () {
[-d / opt / foo] && इको "चेतावनी: फू पहले से स्थापित है। अधिलेखित हो जाएगा।" > और 2
}
check_previous_install
गूंज "संस्थापन फू ..."
उपरोक्त, एकमात्र अंतर होने के बावजूद कि एक लाइन को एक फ़ंक्शन में रिफैक्ट किया गया है, /opt/fooमौजूद नहीं होने पर समाप्त हो जाएगा । ऐसा इसलिए है क्योंकि यह तथ्य कि यह मूल रूप से काम करता है, एक विशेष अपवाद है set -e। जब a && bनॉनजरो लौटता है, तो इसे नजरअंदाज कर दिया जाता है set -e। हालाँकि, अब यह एक फ़ंक्शन है, फ़ंक्शन का एक्ज़िट कोड उस कमांड के एग्ज़िट कोड के बराबर है, और नॉनज़ेरो लौटने वाला फ़ंक्शन चुपचाप स्क्रिप्ट को समाप्त कर देगा।
सेट
IFS = $ '\ n' रीड -d '' -r -a config_vars <config
ऊपर config_varsफ़ाइल से सरणी को पढ़ा जाएगा config। जैसा कि लेखक का इरादा हो सकता है, यह configगायब होने पर एक त्रुटि के साथ समाप्त होता है। जैसा कि लेखक का इरादा नहीं हो सकता है, यह चुपचाप समाप्त हो जाता है अगर configएक नई पंक्ति में समाप्त नहीं होता है। यदि set -eयहां उपयोग नहीं किया गया था, तो config_varsफ़ाइल की सभी लाइनें शामिल होंगी या नहीं यह एक नई पंक्ति में समाप्त हो गई है।
उदात्त पाठ के उपयोगकर्ता (और अन्य पाठ संपादक जो नए सिरे से गलत तरीके से संभालते हैं), सावधान रहें।
सेट
should_audit_user () {
स्थानीय समूह समूह = "$ (समूह" $ 1 ")"
$ समूहों में समूह के लिए; करना
अगर ["$ समूह" = ऑडिट]; फिर वापसी 0; फाई
किया हुआ
वापसी 1
}
अगर "$ उपयोगकर्ता" चाहिए फिर
लकड़हारा 'ब्लाह'
फाई
यहाँ लेखक यथोचित अपेक्षा कर सकता है कि यदि किसी कारण से उपयोगकर्ता $userमौजूद नहीं है, तो groupsकमांड विफल हो जाएगी और उपयोगकर्ता को कुछ कार्य करने की अनुमति देने के बजाय स्क्रिप्ट समाप्त हो जाएगी। हालांकि, इस मामले में set -eसमाप्ति कभी भी प्रभावी नहीं होती है। यदि $userकिसी कारण से नहीं मिल रहा है, तो स्क्रिप्ट को समाप्त करने के बजाय, should_audit_userफ़ंक्शन गलत डेटा लौटाएगा जैसे कि set -eप्रभाव में नहीं था।
यह एक ifबयान के हालत भाग से आह्वान किए गए किसी भी फ़ंक्शन पर लागू होता है , चाहे कितना भी गहरा घोंसला क्यों न हो, इसे परिभाषित नहीं किया जाता है, भले ही आप set -eइसे फिर से अंदर चलाते हों । ifकिसी भी बिंदु पर उपयोग पूरी तरह से set -eतब तक प्रभाव को निष्क्रिय कर देता है जब तक कि हालत ब्लॉक को पूरी तरह से निष्पादित नहीं किया जाता है। यदि लेखक को इस नुकसान के बारे में पता नहीं है, या सभी संभावित स्थितियों में उनके पूरे कॉल स्टैक को नहीं जानता है, जिसमें कोई फ़ंक्शन कहा जा सकता है, तो वे छोटी गाड़ी कोड लिखेंगे और प्रदान की गई सुरक्षा की झूठी भावना set -eकम से कम आंशिक रूप से होगी दोष।
भले ही लेखक इस नुकसान के बारे में पूरी तरह से अवगत हो, लेकिन वर्कअराउंड कोड को उसी तरह से लिखना है जैसे कोई इसे बिना लिखे set -e, प्रभावी रूप से उस स्विच को बेकार से कम प्रदान करता है; न केवल लेखक को मैनुअल एरर हैंडलिंग कोड लिखना set -eपड़ता है, जैसा कि प्रभाव में नहीं था, लेकिन set -eहो सकता है कि उपस्थिति ने उन्हें यह सोचकर बेवकूफ बनाया हो कि उन्हें नहीं करना है।
कुछ और कमियां set -e:
- यह मैला कोड को प्रोत्साहित करता है। त्रुटि हैंडलर के बारे में पूरी तरह से भूल गए हैं, इस उम्मीद में कि जो भी विफल हुआ वह त्रुटि को कुछ समझदार तरीके से रिपोर्ट करेगा। हालांकि,
let x++ऊपर जैसे उदाहरणों के साथ , यह मामला नहीं है। यदि स्क्रिप्ट अप्रत्याशित रूप से मर जाती है, तो यह आमतौर पर चुपचाप होता है, जो डिबगिंग में बाधा उत्पन्न करता है। यदि स्क्रिप्ट नहीं मरती है और आप इसकी उम्मीद करते हैं (पिछली बुलेट बिंदु देखें), तो आपके हाथ में एक अधिक सूक्ष्म और कपटी बग है।
- यह लोगों को सुरक्षा की झूठी भावना में ले जाता है। फिर से देखें
if-कंडिशन बुलेट बिंदु।
- जिन स्थानों पर शेल समाप्त होता है, वे शेल या शेल संस्करणों के बीच संगत नहीं होते हैं। गलती से एक स्क्रिप्ट लिखना संभव है,
set -eजो उन संस्करणों के साथ जुड़ने के व्यवहार के कारण बैश के पुराने संस्करण पर अलग-अलग व्यवहार करता है ।
set -eएक विवादास्पद मुद्दा है, और आसपास के मुद्दों से अवगत कुछ लोग इसके खिलाफ सलाह देते हैं, जबकि कुछ अन्य लोग केवल सावधानी बरतने की सलाह देते हैं जबकि यह नुकसान जानने के लिए सक्रिय है। ऐसे कई शेल स्क्रिप्टिंग वाले न्यूबाय हैं, जो set -eसभी स्क्रिप्ट्स को कैच-ऑल के रूप में त्रुटि की स्थिति के लिए सुझाते हैं, लेकिन वास्तविक जीवन में यह उस तरह से काम नहीं करता है।
set -e शिक्षा का कोई विकल्प नहीं है।