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


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

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


141
2018-05-19 16:39


मूल


यहां एक संबंधित धागा है: stackoverflow.com/questions/64786/error-handling-in-bash/... - Stefan Lasiewski


जवाब:


set -e यदि कोई सबकॉमैंड या पाइपलाइन गैर-शून्य स्थिति देता है तो खोल को बाहर निकलने का कारण बनता है।

साक्षात्कारकर्ता शायद उत्तर की तलाश कर रहा था:

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

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

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

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


146
2017-08-09 21:01



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


से 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.

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


33
2018-05-19 16:43



मुखौटा असली / अन्य समस्याएं, हाँ, मुझे लगता है कि मैं इसे देख सकता था ... मैं खतरनाक होने के उदाहरण के साथ आने के लिए संघर्ष कर रहा था, साथ ही ... - cpbills
के लिए मैनपेज है set! मैं हमेशा खत्म होता हूं builtin(1)। धन्यवाद। - Jared Beck
मैं कैसे जानता हूं कि दस्तावेज के लिए set में बीफउंड है man 1 bash?? और कोई भी कैसे ढूंढ पाएगा -e के लिए विकल्प set एक मैनुअल पेज में कीवर्ड जो इतना बड़ा है? आप बस नहीं कर सकते /-e यहाँ ढूँढे - Blauhirn
@Blauhirn का उपयोग कर help set - Blauhirn


इस बात पर ध्यान दिया जाना चाहिए कि 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 कुछ परिस्थितियों में काम करता है।

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

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

मुझे लगता है कि जब खतरे समझ में नहीं आता है set -e खेल में आता है और जब यह कुछ अवैध धारणा के तहत गलत तरीके से उस पर भरोसा नहीं करता है।

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


19
2018-05-19 22:39



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


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

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

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

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

या शायद यह एक अच्छा स्पष्टीकरण है: http://www.mail-archive.com/debian-bugs-dist@lists.debian.org/msg473314.html


13
2018-05-19 17:03



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


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

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


9
2018-05-19 16:46



यह तो दिलचस्प है। मैंने एक स्क्रिप्ट में खोले गए अनुमतियों के बारे में नहीं सोचा जो समय से मर जाता है लेकिन मैं देख सकता हूं कि खतरनाक माना जा रहा है। इस प्रश्नोत्तरी का मजेदार हिस्सा यह है कि आप किसी संदर्भ सामग्री जैसे मनुष्य या Google का उपयोग नहीं कर सकते हैं और यदि आप पूरी तरह उत्तर नहीं दे सकते हैं तो इसका उत्तर न दें। - egorgry
यह सिर्फ मूर्खतापूर्ण है, मैं इस नियोक्ता पर पुनर्विचार करता हूं ... मजाक कर रहा हूं (तरह)। ज्ञान का एक मजबूत आधार होना अच्छा है, लेकिन आईटी काम का आधा जानकारी जानना / कहां / ढूंढना है ... उम्मीद है कि आवेदकों को स्कोर करते समय वे इसे समझने के लिए पर्याप्त समझदार थे। एक तरफ नोट पर, मैं देखता / नहीं / उपयोग करता हूं set -eवास्तव में, मेरे लिए यह आपकी स्क्रिप्ट में त्रुटि जांच को अनदेखा करने के लिए आलस्य की बात करता है ... इसलिए इसे ध्यान में रखें, इस नियोक्ता के साथ भी ... यदि वे इसे बहुत उपयोग करते हैं, तो उनकी स्क्रिप्ट कैसी दिखती हैं, कि आप अनिवार्य रूप से बनाए रखना होगा ... - cpbills
उत्कृष्ट बिंदु @cpbills। मुझे स्क्रिप्ट में सेट-ए के लिए कोई भी उपयोग नहीं दिखता है और शायद यही कारण है कि यह मुझे इतना रोक दिया। मैं सभी प्रश्न पोस्ट करना चाहता हूं क्योंकि कुछ वास्तव में अच्छे हैं और कुछ वास्तव में निराशाजनक और इस तरह यादृच्छिक हैं। - egorgry
मैंने इसे कई सिस्टम क्रॉन नौकरियों में देखा है ... - Andrew


set -e कुछ स्थितियों के अलावा, एक nonzero निकास कोड का सामना करना पड़ता है, तो स्क्रिप्ट को समाप्त करता है। कुछ शब्दों में इसके उपयोग के खतरों को पूरा करने के लिए: यह व्यवहार नहीं करता है कि लोग यह कैसे सोचते हैं।

मेरी राय में, इसे खतरनाक हैक के रूप में माना जाना चाहिए जो केवल संगतता उद्देश्यों के लिए मौजूद है। set -e कथन उस भाषा से खोल नहीं बदलता है जो त्रुटि कोड का उपयोग ऐसी भाषा में करता है जो अपवाद-नियंत्रण नियंत्रण प्रवाह का उपयोग करता है, यह केवल उस व्यवहार को अनुकरण करने के लिए खराब प्रयास करता है।

ग्रेग वूलेज के खतरों पर बहुत कुछ कहना है set -e:

दूसरे लिंक में, अनजान और अप्रत्याशित व्यवहार के कई उदाहरण हैं set -e

के अनजान व्यवहार के कुछ उदाहरण set -e (कुछ ऊपर विकी लिंक से लिया गया):

  • सेट-ए
    x = 0
    एक्स ++ दें
    गूंज "एक्स $ x है"
    उपरोक्त शेल स्क्रिप्ट को समय से बाहर निकलने का कारण बन जाएगा, क्योंकि let x++ 0 देता है, जिसका इलाज किया जाता है let एक गलत मूल्य के रूप में कीवर्ड और एक nonzero निकास कोड में बदल गया। set -e यह नोटिस करता है, और चुपचाप स्क्रिप्ट को समाप्त करता है।
  • सेट-ए
    [-d / opt / foo] && echo "चेतावनी: foo पहले से स्थापित है। ओवरराइट होगा।" > और 2
    echo "foo इंस्टॉल करना ..."
    

    उपर्युक्त कार्यों की अपेक्षा की जाती है, अगर चेतावनी छापती है /opt/foo पहले से मौजूद है

    सेट-ए
    check_previous_install () {
        [-d / opt / foo] && echo "चेतावनी: foo पहले से स्थापित है। ओवरराइट होगा।" > और 2
    }
    
    check_previous_install
    echo "foo इंस्टॉल करना ..."
    

    उपरोक्त, केवल अंतर के बावजूद कि एक पंक्ति में एक पंक्ति को दोबारा क्रियान्वित किया गया है, तो समाप्त हो जाएगा /opt/foo अस्तित्व में नहीं है। ऐसा इसलिए है क्योंकि यह तथ्य मूल रूप से काम करता है, यह एक विशेष अपवाद है set -eका व्यवहार कब a && b nonzero देता है, इसे अनदेखा किया जाता है set -e। हालांकि, अब यह एक फ़ंक्शन है, फ़ंक्शन का निकास कोड उस कमांड के निकास कोड के बराबर है, और फ़ंक्शन नॉनज़रो को स्क्रिप्ट को चुपचाप समाप्त कर देगा।

  • सेट-ए
    आईएफएस = $ '\ n' read -d '' -r -a config_vars <config
    

    उपरोक्त सरणी पढ़ेगा config_vars फ़ाइल से config। जैसा कि लेखक का इरादा हो सकता है, यह एक त्रुटि के साथ समाप्त होता है config लापता है। जैसा कि लेखक का इरादा नहीं हो सकता है, यह चुपचाप समाप्त हो जाता है config एक नई लाइन में खत्म नहीं होता है। अगर set -e तब यहां इस्तेमाल नहीं किया गया था config_vars फ़ाइल की सभी पंक्तियां होंगी चाहे वह एक नई लाइन में समाप्त हो या नहीं।

    सब्लिमे टेक्स्ट के उपयोगकर्ता (और अन्य टेक्स्ट एडिटर्स जो न्यूलाइन को गलत तरीके से संभालते हैं), सावधान रहें।

  • सेट-ए
    
    should_audit_user () {
        स्थानीय समूह समूह = "$ (समूह" $ 1 ")"
        $ समूहों में समूह के लिए; करना
            अगर ["$ समूह" = लेखा परीक्षा]; फिर 0 लौटें; फाई
        किया हुआ
        वापसी 1
    }
    
    अगर चाहिए_audit_user "$ उपयोगकर्ता"; फिर
        लॉगर 'ब्लाह'
    फाई
    

    यहां लेखक शायद उम्मीद कर सकते हैं कि अगर किसी कारण से उपयोगकर्ता $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 उन संस्करणों के बीच tweaked किया गया है।

set -e एक विवादास्पद मुद्दा है, और कुछ लोगों को इसके आसपास के मुद्दों के बारे में पता है, इसके खिलाफ अनुशंसा करते हैं, जबकि कुछ अन्य केवल देखभाल करने की सलाह देते हैं जबकि यह नुकसान को जानने के लिए सक्रिय है। सिफारिश करने वाले कई शैल स्क्रिप्टिंग नए लोग हैं set -eगलतियों के रूप में सभी स्क्रिप्ट पर सभी त्रुटियों के लिए, लेकिन वास्तविक जीवन में यह इस तरह से काम नहीं करता है।

set -e शिक्षा के लिए कोई विकल्प नहीं है।


5
2018-04-27 23:06





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


2
2018-05-19 18:07



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


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


0
2018-06-22 19:00