यदि आप विकास और प्रोडक्शन में वेब ऐप्स को प्रभावी ढंग से प्रबंधित करना चाहते हैं, तो आपको पर्यावरण चर को समझना होगा।
यह हमेशा ऐसा नहीं था। कुछ साल पहले, शायद ही कोई अपने Rails ऐप्स को पर्यावरण चर के साथ कॉन्फ़िगर कर रहा था। लेकिन फिर Heroku हुआ।
Heroku ने डेवलपर्स को 12-फैक्टर ऐप दृष्टिकोण से परिचित कराया। उनके 12-फैक्टर ऐप मैनिफेस्टो में वे आसानी से डिप्लॉय होने वाले ऐप्स बनाने के लिए अपनी कई सर्वोत्तम प्रथाओं को निर्धारित करते हैं। पर्यावरण चर पर अनुभाग विशेष रूप से प्रभावशाली रहा है।
बारह-फैक्टर ऐप कॉन्फ़िगरेशन को पर्यावरण चर में संग्रहीत करता है (अक्सर env vars या env तक छोटा)। Env vars को किसी भी कोड को बदले बिना डिप्लॉय के बीच बदलना आसान है; कॉन्फ़िग फ़ाइलों के विपरीत, उनके गलती से कोड रेपो में चेक इन होने की बहुत कम संभावना है; और कस्टम कॉन्फ़िग फ़ाइलों या अन्य कॉन्फ़िग तंत्र जैसे Java सिस्टम प्रॉपर्टीज के विपरीत, वे एक भाषा- और OS-अज्ञेय मानक हैं।
अधिक Rubyists पहले से कहीं अधिक पर्यावरण चर का उपयोग कर रहे हैं। लेकिन अक्सर यह एक कार्गो-कल्ट तरीके से होता है। हम वास्तव में यह समझे बिना इन चीजों का उपयोग कर रहे हैं कि वे कैसे काम करते हैं।
यह पोस्ट आपको दिखाएगी कि पर्यावरण चर वास्तव में कैसे काम करते हैं - और शायद अधिक महत्वपूर्ण बात, वे कैसे काम *नहीं* करते। हम आपके Rails ऐप्स में पर्यावरण चर को प्रबंधित करने के कुछ सबसे सामान्य तरीकों का भी पता लगाएंगे। आइए शुरू करें!
नोट: आप यहां पर्यावरण चर सुरक्षित करने के बारे में पढ़ सकते हैं।
हर प्रक्रिया के पास पर्यावरण चर का अपना सेट होता है
आप अपने सर्वर पर जो भी प्रोग्राम चलाते हैं, उसके पास कम से कम एक प्रक्रिया होती है। उस प्रक्रिया को पर्यावरण चर का अपना सेट मिलता है। एक बार जब उसके पास वे होते हैं, तो उस प्रक्रिया के बाहर कुछ भी उन्हें बदल नहीं सकता।
शुरुआती लोग जो समझने योग्य गलती करते हैं, वह यह सोचना है कि पर्यावरण चर किसी तरह सर्वर-वाइड हैं। Heroku जैसी सेवाएं इसे ऐसा दिखाती हैं जैसे पर्यावरण चर सेट करना डिस्क पर एक कॉन्फ़िग फ़ाइल संपादित करने के बराबर है। लेकिन पर्यावरण चर कॉन्फ़िग फ़ाइलों की तरह कुछ भी नहीं हैं।
आप अपने सर्वर पर जो भी प्रोग्राम चलाते हैं, उसे लॉन्च करने के क्षण में पर्यावरण चर का अपना सेट मिलता है।
हर प्रक्रिया का अपना पर्यावरण होता है।
पर्यावरण चर अपनी प्रक्रिया के साथ मरते हैं
क्या आपने कभी कोई पर्यावरण चर सेट किया है, रीबूट किया और पाया कि यह चला गया था? चूंकि पर्यावरण चर प्रक्रियाओं से संबंधित हैं, इसका मतलब है कि जब भी प्रक्रिया बंद होती है, आपका पर्यावरण चर चला जाता है।
आप इसे एक IRB सत्र में एक पर्यावरण चर सेट करके, इसे बंद करके, और दूसरे IRB सत्र में चर तक पहुंचने का प्रयास करके देख सकते हैं।
जब कोई प्रक्रिया बंद होती है, तो उसके पर्यावरण चर खो जाते हैं
यही सिद्धांत आपको सर्वर रीबूट होने पर, या जब आप अपने शेल से बाहर निकलते हैं तो पर्यावरण चर खोने का कारण बनता है। यदि आप उन्हें सत्रों में बनाए रखना चाहते हैं, तो आपको उन्हें `.bashrc` जैसी किसी प्रकार की कॉन्फ़िगरेशन फ़ाइल में संग्रहीत करना होगा।
एक प्रक्रिया को उसके पैरेंट से पर्यावरण चर मिलते हैं
हर प्रक्रिया का एक पैरेंट होता है। ऐसा इसलिए है क्योंकि हर प्रोग्राम को किसी अन्य प्रोग्राम द्वारा शुरू किया जाना चाहिए।
यदि आप vim लॉन्च करने के लिए अपने bash शेल का उपयोग करते हैं, तो vim का पैरेंट शेल है। यदि आपका Rails ऐप किसी छवि की पहचान करने के लिए imagemagick का उपयोग करता है, तो `identify` प्रोग्राम का पैरेंट आपका Rails ऐप होगा।
चाइल्ड प्रोसेस अपने पैरेंट से env vars इनहेरिट करते हैं
नीचे दिए गए उदाहरण में, मैं अपने IRB प्रोसेस में $MARCO पर्यावरण चर का मान सेट कर रहा हूँ। फिर मैं उस चर का मान इको करने के लिए बैक-टिक्स का उपयोग करके शेल आउट करता हूँ।
चूंकि IRB वह पैरेंट प्रोसेस है जिसे मैंने अभी बनाया है, उसे $MARCO पर्यावरण चर की एक कॉपी मिलती है।
Ruby में सेट किए गए पर्यावरण चर चाइल्ड प्रोसेस द्वारा इनहेरिट किए जाते हैं
पैरेंट अपने बच्चों को भेजे जाने वाले पर्यावरण चर को अनुकूलित कर सकते हैं
डिफ़ॉल्ट रूप से एक चाइल्ड को उसके पैरेंट के हर पर्यावरण चर की कॉपी मिलेगी। लेकिन पैरेंट का इस पर नियंत्रण होता है।
कमांड लाइन से, आप env प्रोग्राम का उपयोग कर सकते हैं। और bash में पैरेंट पर उन्हें सेट किए बिना चाइल्ड पर env vars सेट करने के लिए एक विशेष सिंटैक्स है।
पैरेंट पर उन्हें सेट किए बिना चाइल्ड के लिए पर्यावरण चर सेट करने के लिए env कमांड का उपयोग करें
यदि आप Ruby के अंदर से शेल आउट कर रहे हैं तो आप अपने ENV हैश को अव्यवस्थित किए बिना चाइल्ड प्रोसेस को कस्टम पर्यावरण चर भी प्रदान कर सकते हैं। बस `system` मेथड के साथ निम्नलिखित सिंटैक्स का उपयोग करें:
Ruby के सिस्टम मेथड में कस्टम पर्यावरण चर कैसे पास करें
बच्चे अपने पैरेंट के पर्यावरण चर सेट नहीं कर सकते
चूंकि बच्चों को केवल अपने पैरेंट के पर्यावरण चर की **कॉपी** मिलती है, बच्चे द्वारा किए गए परिवर्तनों का पैरेंट पर कोई प्रभाव नहीं पड़ता।
पर्यावरण चर "वैल्यू द्वारा पास" किए जाते हैं "रेफरेंस द्वारा" नहीं
यहाँ, हम बैक-टिक सिंटैक्स का उपयोग करके शेल आउट करते हैं और एक पर्यावरण चर सेट करने का प्रयास करते हैं। जबकि चर चाइल्ड के लिए सेट होगा, नया मान पैरेंट तक बबल अप नहीं करता।
चाइल्ड प्रोसेस अपने पैरेंट के env vars नहीं बदल सकते
चल रही प्रक्रियाओं के बीच पर्यावरण में परिवर्तन सिंक नहीं होते
नीचे दिए गए उदाहरण में मैं IRB की दो कॉपी साइड बाय साइड चला रहा हूँ। एक IRB सत्र के पर्यावरण में एक चर जोड़ने का दूसरे IRB सत्र पर कोई प्रभाव नहीं पड़ता।
एक प्रक्रिया में पर्यावरण चर जोड़ने से अन्य प्रक्रियाओं के लिए यह नहीं बदलता
आपका शेल सिर्फ पर्यावरण चर सिस्टम के लिए एक UI है।
सिस्टम स्वयं OS कर्नेल का हिस्सा है। इसका मतलब है कि शेल का पर्यावरण चर पर कोई जादुई शक्ति नहीं है। इसे हर दूसरे प्रोग्राम की तरह ही नियमों का पालन करना होगा जो आप चलाते हैं।
पर्यावरण चर शेल चर के समान नहीं हैं
सबसे बड़ी गलतफहमियों में से एक इसलिए होती है क्योंकि शेल अपने स्वयं के "स्थानीय" शेल चर सिस्टम प्रदान करते हैं। स्थानीय चर का उपयोग करने का सिंटैक्स अक्सर पर्यावरण चर के समान होता है। और शुरुआती अक्सर दोनों को भ्रमित करते हैं।
लेकिन स्थानीय चर बच्चों को कॉपी नहीं किए जाते।
पर्यावरण चर शेल चर के समान नहीं हैं
आइए एक उदाहरण देखें। पहले मैं MARCO नामक एक स्थानीय शेल चर सेट करता हूँ। चूंकि यह एक स्थानीय चर है, यह किसी भी चाइल्ड प्रोसेस को कॉपी नहीं किया जाता है। नतीजतन, जब मैं इसे Ruby के माध्यम से प्रिंट करने का प्रयास करता हूँ, तो यह काम नहीं करता।
अगला, मैं स्थानीय चर को पर्यावरण चर में बदलने के लिए export कमांड का उपयोग करता हूँ। अब यह इस शेल द्वारा बनाई गई हर नई प्रक्रिया को कॉपी किया जाता है। अब पर्यावरण चर Ruby के लिए उपलब्ध है।
स्थानीय चर चाइल्ड प्रोसेस के लिए उपलब्ध नहीं हैं। Export स्थानीय चर को पर्यावरण चर में बदल देता है।
व्यवहार में पर्यावरण चर प्रबंधित करना
यह सब वास्तविक दुनिया में कैसे काम करता है? आइए एक उदाहरण करें:
मान लीजिए आपके पास एक ही कंप्यूटर पर चलने वाले दो Rails ऐप्स हैं। आप इन ऐप्स में अपवादों की निगरानी के लिए Honeybadger का उपयोग कर रहे हैं। लेकिन आप एक समस्या में पड़ गए हैं।
आप अपना Honeybadger API कुंजी $HONEYBADGER_API_KEY पर्यावरण चर में संग्रहीत करना चाहेंगे। लेकिन आपके दो ऐप्स में दो अलग-अलग API कुंजियाँ हैं।
एक पर्यावरण चर के दो अलग-अलग मान कैसे हो सकते हैं?
अब तक मुझे आशा है कि आप उत्तर जानते हैं। चूंकि env vars प्रति-प्रक्रिया हैं, और मेरे दो rails ऐप्स अलग-अलग प्रक्रियाओं में चलते हैं, इसलिए कोई कारण नहीं है कि उनमें से प्रत्येक का $HONEYBADGER_API_KEY के लिए अपना मान नहीं हो सकता।
अब एकमात्र सवाल यह है कि इसे कैसे सेट किया जाए। सौभाग्य से कुछ जेम्स हैं जो इसे वास्तव में आसान बनाते हैं।
Figaro
जब आप अपने Rails ऐप में Figaro जेम इंस्टॉल करते हैं, तो config/application.yml में आपके द्वारा दर्ज किए गए किसी भी मान को स्टार्टअप पर Ruby ENV हैश में लोड किया जाएगा।
आप बस जेम इंस्टॉल करें:
# Gemfile gem "figaro"
और application.yml में आइटम जोड़ना शुरू करें। यह बहुत महत्वपूर्ण है कि आप इस फ़ाइल को अपने .gitignore में जोड़ें, ताकि आप गलती से अपने सीक्रेट्स कमिट न करें।
# config/application.yml HONEYBADGER_API_KEY: 12345
Dotenv
Dotenv जेम Figaro के समान है, सिवाय इसके कि यह .env से पर्यावरण चर लोड करता है, और यह YAML का उपयोग नहीं करता।
बस जेम इंस्टॉल करें:
# Gemfile gem 'dotenv-rails'
और अपने कॉन्फ़िगरेशन मानों को .env में जोड़ें - और सुनिश्चित करें कि आप फ़ाइल को git ignore करते हैं ताकि आप गलती से इसे गिटहब पर प्रकाशित न करें।
HONEYBADGER_API_KEY=12345
आप फिर अपने Ruby ENV हैश में मानों तक पहुंच सकते हैं
ENV["HONEYBADGER_API_KEY"]
आप अपने पूर्व-परिभाषित सेट के साथ शेल में कमांड भी चला सकते हैं जैसे:
dotenv ./my_script.sh
Secrets.yml?
क्षमा करें। Secrets.yml - हालांकि कूल है - पर्यावरण चर सेट नहीं करता। इसलिए यह वास्तव में Figaro और dotenv जैसे जेम्स का प्रतिस्थापन नहीं है।
सादा पुराना लिनक्स
बेसिक लिनक्स कमांड का उपयोग करके प्रति ऐप पर्यावरण चर के अद्वितीय सेट को बनाए रखना भी संभव है। एक दृष्टिकोण यह है कि आपके सर्वर पर चलने वाला प्रत्येक ऐप एक अलग उपयोगकर्ता के स्वामित्व में हो। फिर आप ऐप्लिकेशन-विशिष्ट मानों को संग्रहीत करने के लिए उपयोगकर्ता के .bashrc का उपयोग कर सकते हैं।