'सेट-ई' क्या करता है, और इसे खतरनाक क्यों माना जा सकता है?


147

यह सवाल एक प्री-इंटरव्यू क्विज़ पर सामने आया है और यह मुझे पागल बना रहा है। क्या कोई इसका जवाब दे सकता है और मुझे आसानी से डाल सकता है? क्विज़ में किसी विशेष शेल का कोई संदर्भ नहीं है, लेकिन नौकरी विवरण एक यूनिक्स सा के लिए है। फिर सवाल बस यह है ...

'सेट-ई' क्या करता है, और इसे खतरनाक क्यों माना जा सकता है?


जवाबों:


154

set -e शेल से बाहर निकलने का कारण बनता है यदि कोई उप-क्षेत्र या पाइपलाइन एक गैर-शून्य स्थिति लौटाता है।

साक्षात्कारकर्ता शायद जिस उत्तर की तलाश में था:

Init.d स्क्रिप्ट बनाते समय "सेट-ई" का उपयोग करना खतरनाक होगा:

से http://www.debian.org/doc/debian-policy/ch-opersys.html 9.3.2 -

Init.d स्क्रिप्ट में सेट -e का उपयोग करने से सावधान रहें। सही init.d स्क्रिप्ट को लिखने के लिए विभिन्न त्रुटि निकास स्थितियों को स्वीकार करने की आवश्यकता होती है जब डेमॉन पहले से ही init.d स्क्रिप्ट को रद्द किए बिना चल रहे हैं या पहले से ही बंद कर दिए गए हैं, और सामान्य init.d फ़ंक्शन लाइब्रेरीज़ सेट -e के साथ कॉल करने के लिए सुरक्षित नहीं हैं। Init.d स्क्रिप्ट के लिए, अक्सर सेट-ई का उपयोग नहीं करना आसान होता है और इसके बजाय प्रत्येक कमांड के परिणाम को अलग से जांचें।

यह एक साक्षात्कारकर्ता के दृष्टिकोण से एक वैध प्रश्न है क्योंकि यह सर्वर-स्तरीय स्क्रिप्टिंग और स्वचालन के काम करने वाले उम्मीदवारों का पता लगाता है


अच्छी बात। यह तकनीकी रूप से एक त्रुटि के कारण बूट प्रक्रिया को रोक देगा, लेकिन पूरी स्क्रिप्ट को रोकने का कारण नहीं होना चाहिए
मैट

हालाँकि , मैं stackoverflow.com/questions/78497/… से सहमत हूँ , मुझे लगता है कि यह स्टाइल शॉर्ट इनिट चेक के लिए बैश के साथ एक अच्छा फिट पाता है और लक्ष्य वर्कलोड को निष्पादित करने से पहले लॉगिंग या अन्य पर्यावरणीय बंदर पैचिंग करता है। हम अपनी डॉक छवि के लिए इसी नीति का उपयोग करते हैं init स्क्रिप्ट।
3

33

से bash(1):

          -e      Exit immediately if a pipeline (which may consist  of  a
                  single  simple command),  a subshell command enclosed in
                  parentheses, or one of the commands executed as part  of
                  a  command  list  enclosed  by braces (see SHELL GRAMMAR
                  above) exits with a non-zero status.  The shell does not
                  exit  if  the  command that fails is part of the command
                  list immediately following a  while  or  until  keyword,
                  part  of  the  test  following  the  if or elif reserved
                  words, part of any command executed in a && or  ││  list
                  except  the  command  following  the final && or ││, any
                  command in a pipeline but the last, or if the  command’s
                  return  value  is being inverted with !.  A trap on ERR,
                  if set, is executed before the shell exits.  This option
                  applies to the shell environment and each subshell envi-
                  ronment separately (see  COMMAND  EXECUTION  ENVIRONMENT
                  above), and may cause subshells to exit before executing
                  all the commands in the subshell.

दुर्भाग्य से मैं यह सोचने के लिए पर्याप्त रचनात्मक नहीं हूं कि यह खतरनाक क्यों होगा, "स्क्रिप्ट के बाकी हिस्सों को निष्पादित नहीं किया जाएगा" या "यह संभवतः संभवतः वास्तविक समस्याओं का मुखौटा हो सकता है" के अलावा।


1
मास्क असली / अन्य समस्याओं, हाँ, मुझे लगता है कि मैं देख सकता था ... मैं एक उदाहरण के साथ आने के लिए संघर्ष कर रहा था खतरनाक, साथ ही साथ ...
cpbills

के लिए मैनपेज है set! मैं हमेशा खत्म करता हूं builtin(1)। धन्यवाद।
बेरेड बेक

मुझे कैसे पता चलेगा कि इसके लिए दस्तावेज़ीकरण setहोना चाहिए man 1 bash? और कोई व्यक्ति मैन्युअल पेज में कीवर्ड के -eलिए विकल्प कैसे खोज सकेगा setजो इतना बड़ा है? आप /-eयहां केवल खोज नहीं कर सकते
Blauhirn

@ बल्लहिरन का उपयोग करनाhelp set
ब्लौहर्न

19

यह ध्यान दिया जाना चाहिए कि set -eएक स्क्रिप्ट के विभिन्न वर्गों के लिए चालू और बंद किया जा सकता है। यह पूरी स्क्रिप्ट के निष्पादन के लिए नहीं है। यह सशर्त रूप से सक्षम भी हो सकता है। उस ने कहा, मैं कभी भी इसका उपयोग नहीं करता क्योंकि मैं अपनी त्रुटि से निपटने (या नहीं) करता हूं।

some code
set -e     # same as set -o errexit
more code  # exit on non-zero status
set +e     # same as set +o errexit
more code  # no exit on non-zero status

यह भी उल्लेखनीय है कि यह trapकमांड पर बैश मैन पेज सेक्शन से है जो यह भी बताता है कि set -eकुछ परिस्थितियों में कैसे कार्य करता है।

ERR ट्रैप को तब निष्पादित नहीं किया जाता है जब विफल कमांड कमांड लिस्ट का कुछ समय या कीवर्ड के तुरंत बाद या अगर स्टेटमेंट में टेस्ट का हिस्सा है, तो एक && या ⎪⎪ लिस्ट में निष्पादित कमांड का हिस्सा है, या यदि कमांड कमांड का हिस्सा है, तो निष्पादित नहीं किया जाता है वापसी मूल्य के माध्यम से उलटा किया जा रहा है! ये वही स्थितियां हैं जो एरेक्सिट विकल्प द्वारा पालन की जाती हैं।

तो कुछ ऐसी स्थितियां हैं जिनके तहत गैर-शून्य स्थिति से बाहर निकलने का कारण नहीं होगा।

मुझे लगता है कि यह खतरा तब नहीं है जब यह समझ में set -eआता है कि यह कब खेल में आता है और कब गलत तरीके से निर्भर करता है।

कृपया यह भी देखें कि BashFAQ / 105 क्यों सेट नहीं करता है (या सेट -o एरेक्सिट, या ट्रैप ईआरआर) क्या उम्मीद करते हैं?


प्रश्न से थोड़ा विचलित होते हुए, यह उत्तर वास्तव में वही है जिसकी मुझे तलाश है: इसे स्क्रिप्ट के छोटे से हिस्से के लिए बंद करना!
Stephan Bijzitter

13

ध्यान रखें कि यह नौकरी साक्षात्कार के लिए एक प्रश्नोत्तरी है। प्रश्न वर्तमान कर्मचारियों द्वारा लिखे गए हो सकते हैं, और वे गलत हो सकते हैं। यह जरूरी बुरा नहीं है, और हर कोई गलतियाँ करता है, और साक्षात्कार प्रश्न अक्सर समीक्षा के बिना एक अंधेरे कोने में बैठते हैं, और केवल एक साक्षात्कार के दौरान सामने आते हैं।

यह पूरी तरह से संभव है कि 'सेट-ई' कुछ भी नहीं करता है कि हम "खतरनाक" पर विचार करेंगे। लेकिन उस प्रश्न के लेखक का मानना ​​है कि 'सेट-ई' खतरनाक है, अपने स्वयं के अज्ञान या पूर्वाग्रह के कारण। हो सकता है कि उन्होंने एक छोटी-सी खोल स्क्रिप्ट लिखी हो, यह बुरी तरह से बमबारी की, और उन्होंने गलती से सोचा कि 'सेट-ई' को दोष देना है, जब वास्तव में उन्होंने उचित त्रुटि जांच लिखने के लिए उपेक्षा की थी।

मैंने पिछले 2 वर्षों में संभवतः 40 नौकरी के साक्षात्कारों में भाग लिया है, और साक्षात्कारकर्ता कभी-कभी ऐसे प्रश्न पूछते हैं जो गलत हैं, या जिनके उत्तर गलत हैं।

या शायद यह एक चाल का सवाल है, जो कि लंगड़ा होगा, लेकिन पूरी तरह से अप्रत्याशित नहीं।

या शायद यह एक अच्छी व्याख्या है: http://www.mail-archive.com/debian-bugs-dist@lists.debian.org/msg473314.html


1
+1 मैं एक ही नाव में हूँ, और बहुत सारे 'तकनीकी' साक्षात्कार जो मेरे साथ काम कर रहे हैं, कम से कम थोड़ा गुमराह कर रहे हैं।
cpbills

1
वाह। डेबियन सूची पर अच्छा लगता है। साक्षात्कार प्रश्नों की अज्ञानता के लिए +1। मुझे याद है कि एक बार नेटबैक का उत्तर देने के बाद से मुझे 100% यकीन था कि मैं सही था। उन्होंने कहा कि नहीं। मैं घर गया और गुगली की, मैं सही था।
एगोर्री

9

set -e बैश बताता है, एक स्क्रिप्ट में, जब भी कुछ भी गैर-शून्य रिटर्न वैल्यू से बाहर निकलने के लिए।

मैं देख सकता हूं कि यह कैसे कष्टप्रद होगा, और छोटी गाड़ी, खतरनाक के बारे में निश्चित नहीं है, जब तक कि आपने कुछ पर अनुमति नहीं दी थी, और इससे पहले कि आप उन्हें फिर से प्रतिबंधित कर सकें, आपकी स्क्रिप्ट मर गई।


यह तो दिलचस्प है। मैंने ऐसी स्क्रिप्ट के बारे में नहीं सोचा था जो समय से पहले मर जाती है, लेकिन मुझे लगता है कि खतरनाक माना जा रहा है। इस क्विज़ का मज़ेदार हिस्सा यह है कि आप किसी भी संदर्भ सामग्री जैसे कि आदमी या Google का उपयोग नहीं कर सकते हैं और यदि आप पूरी तरह से उत्तर नहीं दे सकते हैं तो इसका जवाब बिल्कुल भी न दें।
एगोर्री

6
यह सिर्फ मूर्खतापूर्ण है, मैं इस नियोक्ता पर पुनर्विचार करूंगा ... मजाक कर रहा हूं (तरह का)। ज्ञान का एक मजबूत आधार होना अच्छा है, लेकिन आईटी का आधा काम जानकारी प्राप्त करने के लिए / जहां / पता है ... उम्मीद है कि आवेदकों को स्कोर करते समय वे इसे ध्यान में रखने के लिए पर्याप्त स्मार्ट थे। एक साइड नोट पर, मैं देख रहा हूं / नहीं set -e, वास्तव में, मेरे लिए यह आपके लिपियों में त्रुटि की जांच को अनदेखा करने के लिए आलस्य की बात करता है ... इसलिए ध्यान रखें कि इस नियोक्ता के साथ भी ... यदि वे इसका उपयोग करते हैं। बहुत कुछ, उनकी स्क्रिप्ट्स क्या दिखती हैं, जो आपको अनिवार्य रूप से बनाए रखना होगा ...
cbbills

उत्कृष्ट बिंदु @cpbills। मुझे स्क्रिप्ट में सेट-ई का कोई उपयोग नहीं दिखता है और शायद इसीलिए इसने मुझे इतना स्टम्प किया है। मैं सभी सवालों को पोस्ट करना चाहूंगा क्योंकि कुछ वास्तव में अच्छे हैं और कुछ वास्तव में इस तरह से निराधार और यादृच्छिक हैं।
उदाहरण के लिए

मैंने इसे कई सिस्टम क्रोन नौकरियों में देखा है ...
एंड्रयू

8

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 शिक्षा का कोई विकल्प नहीं है।


2

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


इस जवाब से पूरी तरह सहमत हैं। यह स्वाभाविक रूप से खतरनाक नहीं है, लेकिन यह एक अप्रत्याशित प्रारंभिक निकास का अवसर है।
pboin

1
इसने मुझे याद दिलाया कि C ++ मेरा एक प्रोफेसर है जो हमेशा एक कार्यक्रम में एक प्रविष्टि बिंदु / एकल निकास बिंदु नहीं होने के लिए मेरे असाइनमेंट से अंक खींच रहा था। मुझे लगा कि यह विशुद्ध रूप से एक 'सिद्धांत' है, लेकिन यह सेट-ई व्यवसाय निश्चित रूप से यह बताता है कि कैसे और क्यों चीजें पूरी तरह से नियंत्रण से बाहर हो सकती हैं। अंततः कार्यक्रम नियंत्रण और नियतत्ववाद के बारे में हैं, और समय से पहले समाप्ति के साथ आप दोनों को छोड़ देते हैं।
मार्सिन

0

@ मार्सिन के उत्तर के और अधिक ठोस उदाहरण के रूप में जिसने मुझे व्यक्तिगत रूप से काट लिया है, कल्पना कीजिए कि rm foo/bar.txtआपकी लिपि में कहीं एक रेखा थी। आमतौर पर कोई बड़ी बात foo/bar.txtनहीं अगर वास्तव में मौजूद नहीं है। हालाँकि set -eवर्तमान के साथ अब आपकी स्क्रिप्ट जल्दी समाप्त हो जाएगी! उफ़।

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