आप सभी तरह से ए क्विक फिक्स पर जा सकते हैं, लेकिन यह जरूरी नहीं कि सबसे अच्छा विकल्प हो। इसलिए मैं यह सब पहले पढ़ने की सलाह देता हूं।
rc.local
त्रुटियों को बर्दाश्त नहीं करता है।
rc.local
बुद्धिमानी से त्रुटियों से उबरने का मार्ग प्रदान नहीं करता है। यदि कोई आदेश विफल रहता है, तो वह चलना बंद कर देता है। पहली पंक्ति, #!/bin/sh -e
यह -e
ध्वज के साथ आह्वान किए गए शेल में निष्पादित होने का कारण बनता है । -e
झंडा क्या एक स्क्रिप्ट बनाता है (इस मामले में, है rc.local
) पहली बार एक आदेश यह भीतर असफल होता है बंद करो।
आप rc.local
इस तरह का व्यवहार करना चाहते हैं । यदि कोई कमांड विफल हो जाता है, तो आप नहीं चाहते कि जो भी अन्य स्टार्टअप कमांड सफल हो रहे हैं, उस पर निर्भर रहना जारी रखें।
इसलिए यदि कोई कमांड विफल रहता है, तो बाद की कमांड नहीं चलेगी। यहां समस्या यह है कि /script.sh
यह नहीं चला (ऐसा नहीं है कि यह विफल रहा, नीचे देखें), इसलिए सबसे अधिक संभावना है कि कुछ आदेश विफल होने से पहले। लेकिन कौन सा?
क्या यह था /bin/chmod +x /script.sh
?
नहीं।
chmod
किसी भी समय ठीक चलता है। बशर्ते उस फाइलसिस्टम को शामिल किया /bin
गया है, जिसे आप चला सकते हैं /bin/chmod
। और रनों /bin
से पहले घुड़सवार है rc.local
।
जब जड़ के रूप में चलाया जाता है, तो /bin/chmod
शायद ही कभी असफल होता है। यह विफल हो जाएगा यदि यह जिस फ़ाइल पर काम करता है वह केवल-पढ़ने के लिए है, और विफल हो सकता है यदि फाइलसिस्टम यह समर्थित अनुमतियों पर नहीं है। न ही यहां होने की संभावना है।
वैसे, केवलsh -e
एक ही कारण है कि यह वास्तव में एक समस्या है अगर chmod
असफल हो जाए। जब आप अपने दुभाषिया को स्पष्ट रूप से लागू करके एक स्क्रिप्ट फ़ाइल चलाते हैं, तो इससे कोई फर्क नहीं पड़ता कि क्या फ़ाइल निष्पादन योग्य है। अगर यह कहा जाता है कि केवल /script.sh
फ़ाइल के निष्पादन योग्य बिट मामला होगा। चूंकि यह कहता है sh /script.sh
, जब तक यह चलता है (जब तक यह /script.sh
खुद को कॉल नहीं करता है , जो इसे निष्पादित करने में विफल नहीं हो सकता है, लेकिन यह संभावना नहीं है कि यह कॉल करता है)।
तो क्या असफल रहा?
sh /home/incero/startup_script.sh
अनुत्तीर्ण होना। लगभग निश्चित रूप से।
हमें पता है कि यह भाग गया, क्योंकि यह डाउनलोड हुआ /script.sh
।
(अन्यथा, यह सुनिश्चित करना महत्वपूर्ण होगा कि यह चला हो, अगर किसी तरह /bin
से पथ में नहीं था - rc.local
जरूरी नहीं कि PATH
आपके पास जब आप लॉग इन हों तो आपके पास भी ऐसा ही हो। यदि आप रास्ते /bin
में नहीं थे rc.local
, तो की आवश्यकता होगी sh
के रूप में चलाने के लिए /bin/sh
। के बाद से इसे चलाने की थी, /bin
में है PATH
, जिसका अर्थ है कि आप अन्य आदेशों में स्थित हैं चला सकते हैं /bin
पूरी तरह से उनके नाम योग्यता के बिना,। उदाहरण के लिए, आप बस चला सकते हैं chmod
के बजाय /bin/chmod
। हालांकि, अपनी शैली के अनुरूप में rc.local
, sh
जब भी मैं आपको उन्हें चलाने का सुझाव दे रहा हूँ, को छोड़कर , सभी आदेशों के लिए मैंने पूरी तरह से योग्य नामों का उपयोग किया है।)
हमें पूरा यकीन है कि /bin/chmod +x /script.sh
कभी नहीं चला गया (या आप देखेंगे कि /script.sh
इसे निष्पादित किया गया था)। और हम जानते हैं कि sh /script.sh
या तो नहीं चलाया गया था।
लेकिन इसे डाउनलोड किया गया /script.sh
। यह सफल रहा! यह कैसे विफल हो सकता है?
सफलता के दो अर्थ
जब कोई व्यक्ति सफल होता है, तो दो अलग-अलग चीजें होती हैं जिनका मतलब हो सकता है:
- यह वही किया जो आप इसे करना चाहते थे।
- इसने बताया कि यह सफल रहा।
और इसलिए यह विफलता के लिए है। जब कोई व्यक्ति कहता है कि कोई आदेश विफल हो गया है, तो इसका मतलब हो सकता है:
- यह वह नहीं करता था जो आप करना चाहते थे।
- इसने बताया कि यह विफल रहा।
एक स्क्रिप्ट sh -e
, जैसे rc.local
, पहली बार एक कमांड रिपोर्ट के चलने से बंद हो जाएगी, जो विफल हो गई । इससे कोई फर्क नहीं पड़ता कि वास्तव में कमांड ने क्या किया।
जब तक आप startup_script.sh
विफलता की रिपोर्ट करने का इरादा नहीं करते जब वह ऐसा करता है जो आप चाहते हैं, तो यह एक बग है startup_script.sh
।
- कुछ कीड़े स्क्रिप्ट को ऐसा करने से रोकते हैं जो आप करना चाहते हैं। वे प्रभावित करते हैं कि प्रोग्रामर इसके साइड इफेक्ट्स को क्या कहते हैं ।
- और कुछ कीड़े किसी स्क्रिप्ट को सही तरीके से रिपोर्ट करने से रोकते हैं कि वह सफल हुआ या नहीं। वे प्रभावित करते हैं कि प्रोग्रामर इसके रिटर्न वैल्यू को कहते हैं (जो इस मामले में एक निकास स्थिति है )।
यह सबसे अधिक संभावना है कि startup_script.sh
उसने वह सब किया जो उसे रिपोर्ट करना चाहिए, सिवाय इसके कि वह विफल रहा।
कैसे सफलता या विफलता की रिपोर्ट की जाती है
एक स्क्रिप्ट शून्य या अधिक आदेशों की एक सूची है। प्रत्येक कमांड में एक निकास स्थिति है। यह मानते हुए कि स्क्रिप्ट को चलाने में वास्तव में कोई विफलता नहीं है (उदाहरण के लिए, यदि दुभाषिया इसे चलाते समय स्क्रिप्ट की अगली पंक्ति नहीं पढ़ सकता है), एक स्क्रिप्ट की निकास स्थिति है:
0
(सफलता) यदि स्क्रिप्ट रिक्त थी (यानी, कोई आदेश नहीं था)।
N
, यदि स्क्रिप्ट कमांड के परिणामस्वरूप समाप्त हो गई, तो कुछ निकास कोड कहां है।exit N
N
- स्क्रिप्ट में चलने वाले अंतिम कमांड का निकास कोड, अन्यथा।
जब एक निष्पादन योग्य रन होता है, तो यह अपने स्वयं के निकास कोड की रिपोर्ट करता है - वे केवल स्क्रिप्ट के लिए नहीं हैं। (और तकनीकी रूप से, स्क्रिप्ट से बाहर निकलने के कोड वे रन कोड हैं जो उन्हें चलाने वाले गोले द्वारा लौटाए जाते हैं।)
उदाहरण के लिए, यदि कोई C प्रोग्राम समाप्त होता है exit(0);
, या return 0;
उसके main()
फ़ंक्शन में, कोड 0
ऑपरेटिंग सिस्टम को दिया जाता है, जो उसे कॉलिंग प्रक्रिया प्रदान करता है (उदाहरण के लिए, वह शेल हो सकता है जिसमें से प्रोग्राम चलाया गया था)।
0
कार्यक्रम सफल रहा। हर दूसरी संख्या का मतलब है कि यह विफल रहा। (इस तरह, अलग-अलग संख्याएँ कभी-कभी अलग-अलग कारणों से संदर्भित हो सकती हैं जो कार्यक्रम विफल रहा।)
फेल होने का मतलब है
कभी-कभी, आप इस उद्देश्य से एक कार्यक्रम चलाते हैं कि यह विफल हो जाएगा। इन स्थितियों में, आप इसकी विफलता को सफलता के रूप में सोच सकते हैं, भले ही यह बग नहीं है कि कार्यक्रम विफलता की रिपोर्ट करता है। उदाहरण के लिए, आप rm
उस फ़ाइल पर उपयोग कर सकते हैं जिस पर आपको संदेह है कि पहले से मौजूद नहीं है, बस यह सुनिश्चित करने के लिए कि यह हटा दिया गया है।
ऐसा ही कुछ हो रहा है शायद startup_script.sh
, बस चलने से पहले। स्क्रिप्ट में चलने वाला अंतिम कमांड शायद विफलता की रिपोर्ट कर रहा है (भले ही इसकी "विफलता" पूरी तरह से ठीक या आवश्यक हो सकती है), जो स्क्रिप्ट रिपोर्ट को विफल बनाता है।
टेस्ट का मतलब फेल होना
एक विशेष प्रकार की कमांड एक परीक्षण है , जिसके द्वारा मेरा मतलब है कि इसके साइड इफेक्ट्स के बजाय इसके वापसी मूल्य के लिए एक कमांड रन। यही है, एक परीक्षण एक कमांड है जिसे चलाया जाता है ताकि इसकी निकास स्थिति की जांच की जा सके (और इस पर कार्य किया जा सके)।
उदाहरण के लिए, मान लीजिए कि मैं भूल जाता हूं यदि 4 के बराबर है 5. सौभाग्य से, मुझे पता है कि शेल स्क्रिप्टिंग:
if [ 4 -eq 5 ]; then
echo "Yeah, they're totally the same."
fi
यहां, परीक्षण [ -eq 5 ]
विफल हो जाता है क्योंकि यह 4 all 5 निकलता है। इसका मतलब यह नहीं है कि परीक्षण सही ढंग से प्रदर्शन नहीं किया था; यह किया। यह काम था कि अगर 4 = 5 की जाँच करें, तो सफलता की रिपोर्ट करें यदि ऐसा है, और यदि नहीं तो विफलता।
आप देखते हैं, शेल स्क्रिप्टिंग में, सफलता का मतलब भी सच हो सकता है , और असफलता का अर्थ असत्य भी हो सकता है ।
भले ही echo
बयान कभी नहीं चलता है, if
एक पूरे के रूप में ब्लॉक सफलता लौटाता है।
हालाँकि, माना जाता है कि मैंने इसे छोटा लिखा है:
[ 4 -eq 5 ] && echo "Yeah, they're totally the same."
यह आम आशुलिपि है। &&
एक बूलियन और ऑपरेटर है। एक &&
अभिव्यक्ति, जिसमें &&
दोनों तरफ के बयान शामिल होते हैं , जब तक कि दोनों पक्ष सही (सफलता) वापस नहीं आते हैं। एक सामान्य और की तरह ।
अगर कोई आपसे पूछे, "क्या डेरेक मॉल गए थे और एक तितली के बारे में सोचते थे?" और तुम्हें पता है कि डेरेक मॉल में नहीं गया था, अगर आपको एक तितली के बारे में सोचा तो उसे परेशान करने की ज़रूरत नहीं है।
इसी तरह, यदि &&
फेल के बाएं को कमांड (असत्य), पूरी &&
अभिव्यक्ति तुरंत विफल (झूठी) हो जाती है। के दाईं ओर का कथन &&
कभी नहीं चलाया जाता है।
यहाँ, [ 4 -eq 5 ]
चलाता है। यह "विफल" (झूठी वापसी) है। तो पूरी &&
अभिव्यक्ति विफल हो जाती है। echo "Yeah, they're totally the same."
कभी नहीं चलता। सब कुछ जैसा कि होना चाहिए व्यवहार किया, लेकिन यह आदेश विफलता की रिपोर्ट करता है (भले ही if
रिपोर्ट सफलता के ऊपर अन्यथा सशर्त हो)।
यदि यह एक स्क्रिप्ट में आखिरी स्टेटमेंट था (और स्क्रिप्ट को इसके पहले किसी बिंदु पर समाप्त करने के बजाय इसे मिला), तो पूरी स्क्रिप्ट विफलता की रिपोर्ट करेगी ।
इसके अलावा बहुत सारे परीक्षण हैं। उदाहरण के लिए, ||
("या") के साथ परीक्षण हैं । हालांकि, उपरोक्त उदाहरण यह समझाने के लिए पर्याप्त होना चाहिए कि परीक्षण क्या हैं, और यह सुनिश्चित करने के लिए प्रभावी ढंग से प्रलेखन का उपयोग करना संभव है कि क्या कोई विशेष विवरण / आदेश एक परीक्षण है।
sh
बनाम sh -e
, पर दोबारा गौर किया
के बाद से लाइन (यह भी देखें इस सवाल के शीर्ष पर) है , ऑपरेटिंग सिस्टम स्क्रिप्ट चलाता है जैसे कि यह कमांड के साथ लागू किया गया:#!
/etc/rc.local
sh -e
sh -e /etc/rc.local
इसके विपरीत, के रूप में अपने अन्य लिपियों, startup_script.sh
चलाने के बिना-e
झंडा:
sh /home/incero/startup_script.sh
नतीजतन वे तब भी भागते रहते हैं जब उनमें एक कमांड विफलता की रिपोर्ट करता है।
यह सामान्य और अच्छा है। अधिकांश स्क्रिप्ट्स के साथ इनवॉइस rc.local
किया जाना चाहिए sh -e
- जिसमें अधिकांश स्क्रिप्ट शामिल हैं - rc.local
नहीं।
बस अंतर याद रखना सुनिश्चित करें:
sh -e
एग्जिट रिपोर्टिंग विफलता के साथ चलने वाली स्क्रिप्ट्स पहली बार एक कमांड होती है जिसमें वे रिपोर्टिंग विफलता से बाहर निकलते हैं।
यह ऐसा है जैसे कि स्क्रिप्ट एक एकल लंबी कमांड थी जिसमें स्क्रिप्ट में सभी कमांड शामिल थे जो &&
ऑपरेटरों के साथ शामिल थे ।
sh
(बिना -e
) के साथ चलने वाली लिपियाँ तब तक चलती रहती हैं जब तक उन्हें एक कमांड नहीं मिलती जो उन्हें समाप्त कर देती है (बाहर निकल जाती है), या स्क्रिप्ट के बहुत अंत तक। प्रत्येक कमांड की सफलता या विफलता अनिवार्य रूप से अप्रासंगिक है (जब तक कि अगली कमांड इसकी जांच न करे)। स्क्रिप्ट अंतिम कमांड रन की निकास स्थिति से बाहर निकलती है।
आपकी स्क्रिप्ट को समझने में मदद करना यह सब के बाद ऐसी विफलता नहीं है
आप अपनी स्क्रिप्ट को यह सोचने से कैसे रोक सकते हैं कि जब यह नहीं हुआ था?
आप देखते हैं कि दौड़ने से ठीक पहले क्या होता है।
यदि एक कमांड विफल हो गया है जब इसे सफल होना चाहिए, तो यह पता लगाएं, और समस्या को ठीक क्यों करें।
यदि कोई आदेश विफल हो गया, और यह सही बात थी, तो उस विफलता की स्थिति को प्रचारित होने से रोकें।
असफलता की स्थिति को प्रचारित करने से रोकने का एक तरीका यह है कि एक और कमांड चलाया जाए जो सफल हो। /bin/true
कोई साइड इफेक्ट नहीं है और सफलता की रिपोर्ट /bin/false
करता है (जैसे कुछ नहीं करता है और असफल भी होता है)।
एक और यह सुनिश्चित करने के लिए है कि स्क्रिप्ट समाप्त हो गई है exit 0
।
जरूरी नहीं कि exit 0
स्क्रिप्ट के अंत में भी यही बात हो । उदाहरण के लिए, एक if
स्क्रिप्ट वहाँ से बाहर हो सकती है, जहाँ स्क्रिप्ट बाहर जाती है।
यह जानना सबसे अच्छा है कि आपकी स्क्रिप्ट विफलता का कारण बनती है, इससे पहले कि वह रिपोर्ट को सफल बनाए। अगर यह वास्तव में किसी तरह से विफल हो रहा है (जो आप इसे करना चाहते हैं वह नहीं करने के अर्थ में), तो आप वास्तव में सफलता की रिपोर्ट करना नहीं चाहते हैं।
एक त्वरित सुधार
यदि आप startup_script.sh
एग्जिट रिपोर्टिंग को सफल नहीं बना सकते हैं, तो आप rc.local
इसे चलाने वाले कमांड को बदल सकते हैं , ताकि कमांड सफलता की रिपोर्ट करे, हालांकि startup_script.sh
नहीं।
वर्तमान में आपके पास है:
sh /home/incero/startup_script.sh
इस कमांड के एक ही साइड इफेक्ट्स हैं (यानी, रनिंग का साइड इफेक्ट startup_script.sh
), लेकिन हमेशा सफलता की रिपोर्ट करता है:
sh /home/incero/startup_script.sh || /bin/true
याद रखें, यह जानना बेहतर है कि startup_script.sh
रिपोर्ट विफलता क्यों है, और इसे ठीक करें।
क्विक फिक्स कैसे काम करता है
यह वास्तव में एक ||
परीक्षण, या परीक्षण का एक उदाहरण है ।
मान लीजिए आप पूछते हैं कि क्या मैंने कचरा निकाला या उल्लू को ब्रश किया। अगर मैंने कचरा निकाला, तो मैं सच में "हां" कह सकता हूं, भले ही मुझे याद न हो कि मैंने उल्लू को ब्रश किया है या नहीं।
||
रनों के बाईं ओर कमान । यदि यह सफल (सत्य) है, तो दाहिने हाथ की ओर नहीं चलना है। इसलिए अगर startup_script.sh
सफलता की रिपोर्ट करें, तो true
आदेश कभी नहीं चलता है।
हालांकि, यदि startup_script.sh
रिपोर्ट में विफलता [मैं कचरा नहीं उठाता] , तो /bin/true
[यदि मैं उल्लू को ब्रश करता हूं ] तो इसका परिणाम होता है।
/bin/true
हमेशा सफलता देता है (या सच है , जैसा कि हम कभी-कभी इसे कहते हैं)। नतीजतन, पूरी कमांड सफल होती है, और अगला कमांड rc.local
चल सकता है।
सफलता / असफलता, सच्चा / झूठा, शून्य / नॉनज़रो पर एक अतिरिक्त नोट।
बेझिझक इसे अनदेखा करें। यदि आप एक से अधिक भाषाओं में प्रोग्राम करते हैं, तो आप इसे पढ़ना चाह सकते हैं, हालांकि (यानी, केवल शेल स्क्रिप्टिंग नहीं)।
शेल स्क्रिप्टर्स के लिए C जैसी प्रोग्रामिंग लैंग्वेज लेना और C प्रोग्रामर्स के लिए शेल स्क्रिप्टिंग को पूरा करना बहुत ही असमंजस की बात है।
शेल स्क्रिप्टिंग में:
0
मतलब सफलता और / या सच का वापसी मूल्य ।
- के अलावा कुछ का एक वापसी मान
0
साधन विफलता और / या झूठी ।
सी प्रोग्रामिंग में:
- का एक वापसी मान
0
साधन झूठी ..
- किसी अन्य वस्तु की वापसी का
0
मतलब सही है ।
- सफलता का क्या अर्थ है और असफलता का क्या अर्थ है, इसके लिए कोई सरल नियम नहीं है। कभी-कभी
0
सफलता का मतलब है, अन्य बार इसका मतलब विफलता है, अन्य बार इसका मतलब है कि आपके द्वारा जोड़े गए दो नंबरों का योग शून्य है। सामान्य प्रोग्रामिंग में रिटर्न मान का उपयोग विभिन्न प्रकार की सूचनाओं की एक विस्तृत विविधता को इंगित करने के लिए किया जाता है।
- एक प्रोग्राम के संख्यात्मक निकास स्थिति को शेल स्क्रिप्टिंग के नियमों के अनुसार सफलता या विफलता का संकेत देना चाहिए। यह है, भले ही
0
आपके सी कार्यक्रम में झूठ का मतलब है, आप अभी भी अपने प्रोग्राम 0
को इसके एक्जिट कोड के रूप में लौटाते हैं यदि आप चाहते हैं कि यह रिपोर्ट करें कि यह सफल हुआ (जो शेल तब सत्य के रूप में व्याख्या करता है )।