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