डेवलपर्स के रूप में, हम अपने कार्यक्रमों को चलाने में इतना समय लगाते हैं कि यह अनदेखा करना आसान है कि वे कैसे बाहर निकलते हैं। और यह महत्वपूर्ण है! जब आपके प्रोग्राम बाहर निकलने पर सही ढंग से व्यवहार करते हैं, तो इससे उन्हें प्रबंधित करना बहुत आसान हो जाता है और मानक devops टूल के साथ काम करने की संभावना बढ़ जाती है।
रूबी प्रोग्राम से बाहर निकलने के कई तरीके हैं। मैंने उनमें से कुछ को नीचे दिखाया है। इस पोस्ट में हम इनमें से प्रत्येक के विवरण पर चर्चा करेंगे, और उनका उपयोग आपके ऐप को एक अच्छा व्यवहार करने वाला यूनिक्स नागरिक बनाने के लिए कैसे किया जा सकता है।
# You can exit by calling a method
exit
exit!
abort("She cannot take any more of this, Captain!")
# ...or by failing to catch an exception
raise("Destroyed...")
fail
# ...or by letting the program end naturally. :)
कोड से बाहर निकलें, और आप
आपके द्वारा Linux और OSX पर चलाए जाने वाले प्रत्येक प्रोग्राम के चलने के समाप्त होने पर एक एक्ज़िट स्टेटस कोड लौटाता है। आप सामान्य रूप से निकास कोड नहीं देखते हैं। इसका उपयोग ओएस द्वारा परदे के पीछे यह निर्धारित करने के लिए किया जाता है कि प्रोग्राम सामान्य रूप से बाहर निकला है या कोई त्रुटि हुई है।
यदि आप बैश का उपयोग कर रहे हैं, तो आप $?
की जांच करके उस प्रोग्राम का एक्ज़िट कोड देख सकते हैं, जिसे आपने अभी-अभी चलाया था पर्यावरणपरिवर्ती तारक। नीचे दिया गया उदाहरण विफलता के लिए, फिर सफलता के लिए निकास कोड दिखाता है।
% ls this-file-doesnt-exist
ls: this-file-doesnt-exist: No such file or directory
blog% echo $?
1
% ls .
bm.rb
% echo $?
0
आम तौर पर, यूनिक्स-आधारित प्रणालियों के लिए नियम यह है कि शून्य का अर्थ सफलता है। गैर-शून्य का अर्थ है विफलता।
यदि आपने कभी &&
. का उपयोग किया है बैश में "ऑपरेटर", फिर आपने स्थिति कोड का उपयोग किया है। नीचे दिए गए उदाहरण में, हम बैश को प्रोग्राम B चलाने के लिए तभी कहते हैं जब प्रोग्राम A सफल हो।
% a && b
इस ट्रिक को आप कई तरह से इस्तेमाल कर सकते हैं। उदाहरण के लिए, हो सकता है कि आप संपत्तियों को पूर्व-संकलित करना चाहें, और उन्हें एक सीडीएन पर अपलोड करना चाहें।
blog% rake assets:precompile && rake cdn:upload_assets
रूबी के साथ एक्ज़िट स्थिति निर्दिष्ट करना
रूबी हमारे लिए बाहर निकलने की स्थिति की बहुत सारी चीजों का ख्याल रखती है। यदि आपका प्रोग्राम सामान्य रूप से बाहर निकलता है, तो यह "सफलता" स्थिति देता है। यदि यह बिना किसी अपवाद के विफल हो जाता है, तो यह "विफलता" का दर्जा देता है। नीचे मैं एक ऐसी स्क्रिप्ट के लिए एक्ज़िट कोड दिखा रहा हूँ जिसने एक अपवाद उठाया है।
% ruby err.rb
err.rb:1:in `<main>': goodbye (RuntimeError)
tmp% echo $?
1
लेकिन क्या होगा यदि आप कोई अनकहा अपवाद नहीं चाहते हैं? क्या होगा यदि आप सफाई से बाहर निकलना चाहते हैं, लेकिन फिर भी एक "विफल" त्रुटि कोड लौटाते हैं? इसके अलावा, क्या होगा यदि आप एक त्रुटि संदेश के साथ एक कस्टम कोड वापस करना चाहते हैं?
सौभाग्य से, यह काफी आसान है। बस exit
. में एक तर्क पास करें समारोह। तर्क एक बूलियन या एक पूर्णांक हो सकता है। यदि यह बूलियन है, तो सत्य का अर्थ है सफलता। अगर यह 0 से एक पूर्णांक है तो इसका मतलब सफलता है।
exit(true) # Exits with "success" code
exit(0) # Exits with "success" code
exit(false) # Exits with "failure" code
exit(1) # Exits with "failure" code
exit(436) # Custom failure error code
कैसे exit
हुड के तहत काम करता है
बाहर निकलने की विधि बस एक SystemExit
उठाती है अपवाद। यदि यह ध्यान में नहीं आता है, तो प्रोग्राम उसी तरह निरस्त हो जाता है जैसे किसी अन्य न आया हुआ अपवाद के साथ होता। यह बहुत अच्छा है, लेकिन इसके कुछ दिलचस्प परिणाम हैं।
यदि आप सभी SystemExit अपवादों को निगलना चाहते हैं, तो आप निकास विधि को तोड़ देंगे। मैंने इसे नीचे के उदाहरण में दिखाया है।
begin
exit 100
rescue SystemExit => e
puts "Tried to exit with status #{ e.status }"
end
puts "...but it never exited, because we swallowed the exception"
# Outputs:
# Tried to exit with status 100
# ...but it never exited, because we swallowed the exception
यह एक और कारण है कि कभी भी Exception
को बचाया नहीं जा सकता है . क्योंकि SystemExit
Exception
. से इनहेरिट करता है , निगलना Exception
निकास को तोड़ देगा।
begin
exit
rescue Exception # never do this
puts "I just broke the exit function!"
end
मानव-पठनीय त्रुटि संदेश
जबकि मशीनों के लिए निकास कोड बहुत अच्छे होते हैं, हम मनुष्य अक्सर थोड़ा सा व्याख्यात्मक पाठ पसंद करते हैं। सौभाग्य से, OS हमें विशेष रूप से त्रुटि संदेशों जैसी चीज़ों के लिए एक आउटपुट स्ट्रीम प्रदान करता है। हां, मैं एसटीडीईआरआर के बारे में बात कर रहा हूं।
आप एसटीडीईआरआर को वैसे ही लिख सकते हैं जैसे आप किसी आईओ ऑब्जेक्ट को लिखते हैं। नीचे दिए गए उदाहरण में मैं एक त्रुटि संदेश लिख रहा हूं और "त्रुटि" स्थिति से बाहर निकल रहा हूं।
STDERR.puts("ABORTED! You forgot to BAR the BAZ")
exit(false)
यह रूबी होने के नाते, निश्चित रूप से एक त्रुटि कोड के साथ stdout और बाहर निकलने के लिए लिखने का एक संक्षिप्त तरीका है। बस abort
का उपयोग करें विधि।
# Write the message to STDERR and exit with an error status code.
abort("ABORTED! You forgot to BAR the BAZ")
at_exit
के जरिए कॉलबैक
रूबी आपको हैंडलर पंजीकृत करने देता है जिसे प्रोग्राम से बाहर निकलने पर कॉल किया जा सकता है। उनमें से एक से अधिक हो सकते हैं - उन्हें उस विपरीत क्रम में बुलाया जाता है जिसमें वे पंजीकृत थे। यह इस तरह दिखता है:
at_exit do
puts "handler 1"
end
at_exit do
puts "handler 2"
end
# Outputs "handler2\nhandler1" on exit
एग्जिट हैंडलर एग्जिट कोड को ओवरराइड कर सकता है। आप इसे हैंडलर के भीतर से बाहर निकलने के लिए कॉल करके करते हैं। भले ही ऐसा लगता है कि यह एक अनंत लूप का कारण बनना चाहिए, ऐसा नहीं है। :)पी>
at_exit do
exit 100
end
exit 0
# This program exits with a code of 100
यदि आप किसी कॉलबैक को कॉल किए बिना बाहर निकलना चाहते हैं, तो आप exit!
. के माध्यम से ऐसा कर सकते हैं तरीका। लेकिन ध्यान रखें कि यदि आपके पास रत्न या अन्य तृतीय-पक्ष कोड है जो उन कॉलबैक पर निर्भर करता है तो इससे समस्या हो सकती है।
एक दिलचस्प एक तरफ
यह पता चला है कि बहुत सारे पुस्तकालय at_exit
. का उपयोग करते हैं आविष्कारशील में - और कुछ हैकी कह सकते हैं - तरीके। उदाहरण के लिए, सिनात्रा at_exit
. का उपयोग करती है वेब ऐप को बूट करने के तरीके के रूप में हुक करें। यह यह सुनिश्चित करने की अनुमति देता है कि सर्वर शुरू होने से पहले आपका सभी कोड लोड हो गया है। यह इस तरह दिखता है:
module Sinatra
class Application < Base
...
at_exit { Application.run! if $!.nil? && Application.run? }
end
इसके बारे में Arkency ब्लॉग पर एक बढ़िया पोस्ट है:क्या हम at_exit का दुरुपयोग कर रहे हैं?