यदि आप Linux या Mac का उपयोग करते हैं, तो हर बार जब आप कोई टर्मिनल खोलते हैं तो आप एक शेल एप्लिकेशन का उपयोग कर रहे होते हैं।
शेल एक इंटरफ़ेस है जो आपके सिस्टम में कमांड निष्पादित करने में आपकी सहायता करता है।
शेल पर्यावरण चर को होस्ट करता है और इसमें कमांड इतिहास और स्वतः पूर्णता जैसी उपयोगी विशेषताएं होती हैं।
अगर आप उस तरह के व्यक्ति हैं जो यह सीखना पसंद करते हैं कि चीजें कैसे काम करती हैं, तो यह पोस्ट आपके लिए एकदम सही होगी!
शेल कैसे काम करता है?
अपना खुद का शेल एप्लिकेशन बनाने के लिए आइए सोचें कि शेल वास्तव में क्या है:
सबसे पहले, एक प्रॉम्प्ट होता है, आमतौर पर आपके वर्तमान उपयोगकर्ता और वर्तमान निर्देशिका जैसी कुछ अतिरिक्त जानकारी के साथ, फिर आप एक कमांड टाइप करते हैं और जब आप एंटर दबाते हैं तो परिणाम आपकी स्क्रीन पर प्रदर्शित होते हैं।
हाँ, यह बहुत बुनियादी लगता है, लेकिन क्या यह आपको कुछ याद नहीं दिलाता?
अगर आप pry
के बारे में सोच रहे हैं तो आप सही हैं!
आपके ऑपरेटिंग सिस्टम के लिए मूल रूप से एक आरईपीएल (रीड-एवल-प्रिंट-लूप) में एक शेल।
यह जानते हुए कि हम आपके शेल का अपना पहला संस्करण लिख सकते हैं :
prompt = "> " print prompt while (input = gets.chomp) break if input == "exit" system(input) print prompt end
यह हमें एक न्यूनतम, लेकिन कार्यात्मक खोल देगा। हम एक पुस्तकालय का उपयोग करके इसे बेहतर बना सकते हैं जिसका उपयोग कई अन्य आरईपीएल जैसे अनुप्रयोग करते हैं।
उस लाइब्रेरी को Readline
. कहा जाता है ।
रीडलाइन लाइब्रेरी का उपयोग करना
रीडलाइन रूबी मानक पुस्तकालय का हिस्सा है, इसलिए स्थापित करने के लिए कुछ भी नहीं है, आपको बस require
की आवश्यकता है यह।
Readline
. का उपयोग करने के लाभों में से एक यह है कि यह हमारे लिए स्वचालित रूप से एक कमांड इतिहास रख सकता है।
यह कमांड प्रॉम्प्ट और कई अन्य चीजों को प्रिंट करने का भी ध्यान रख सकता है।
यहाँ हमारे शेल का v2 है, इस बार Readline
. का उपयोग करते हुए :
require 'readline' while input = Readline.readline("> ", true) break if input == "exit" system(input) end
यह बहुत अच्छा है, हमने दो puts
से छुटकारा पा लिया है शीघ्र और अब हमारे पास Readline
. से कुछ शक्तिशाली क्षमताओं तक पहुंच है . उदाहरण के लिए, हम किसी शब्द को हटाने के लिए कीबोर्ड शॉर्टकट का उपयोग कर सकते हैं (CTRL + W
) या इतिहास भी खोजें (CTRL + R
)!
आइए पूरा इतिहास प्रिंट करने के लिए एक नया कमांड जोड़ें:
require 'readline' while input = Readline.readline("> ", true) break if input == "exit" puts Readline::HISTORY.to_a if input == "hist" # Remove blank lines from history Readline::HISTORY.pop if input == "" system(input) end<ब्लॉककोट>
मजेदार तथ्य:यदि आप इस कोड को pry में आज़माते हैं तो आपको pry का कमांड इतिहास मिल जाएगा! इसका कारण यह है कि pry भी Readline
. का उपयोग कर रहा है , और Readline::HISTORY
साझा स्थिति है।
अब आप hist
type टाइप कर सकते हैं अपना आदेश इतिहास प्राप्त करने के लिए 🙂
स्वतः-पूर्णता जोड़ना
अपने पसंदीदा शेल की स्वतः-पूर्णता सुविधा के लिए धन्यवाद, आप बहुत सारी टाइपिंग को बचाने में सक्षम होंगे। रीडलाइन इस सुविधा को आपके शेल में एकीकृत करना वास्तव में आसान बनाता है।
आइए अपने इतिहास के आदेशों को स्वतः पूर्ण करके प्रारंभ करें।
उदाहरण :
comp = proc { |s| Readline::HISTORY.grep(/^#{Regexp.escape(s)}/) } Readline.completion_append_character = " " Readline.completion_proc = comp ## rest of the code goes here ##जाता है।
इस कोड के साथ आप <tab>
. दबाकर पहले से टाइप किए गए कमांड को स्वतः पूर्ण करने में सक्षम होना चाहिए चाभी। अब इसे एक कदम आगे बढ़ाते हैं और निर्देशिका स्वतः पूर्णता जोड़ें।
उदाहरण :
comp = proc do |s| directory_list = Dir.glob("#{s}*") if directory_list.size > 0 directory_list else Readline::HISTORY.grep(/^#{Regexp.escape(s)}/) end end
completion_proc
संभावित उम्मीदवारों की सूची लौटाता है, इस मामले में हमें केवल Dir.glob
का उपयोग करके यह जांचने की आवश्यकता है कि टाइप की गई स्ट्रिंग निर्देशिका नाम का हिस्सा है या नहीं . रीडलाइन बाकी का ख्याल रखेगी!
सिस्टम विधि को लागू करना
अब आपके पास इतिहास और स्वत:पूर्णता के साथ एक कार्यशील शेल होना चाहिए, कोड की 25 पंक्तियों के लिए बहुत बुरा नहीं है 🙂
लेकिन कुछ ऐसा है जिसके बारे में मैं गहराई से जानना चाहता हूं, ताकि आप इस बारे में कुछ अंतर्दृष्टि प्राप्त कर सकें कि वास्तव में किसी कमांड को निष्पादित करने के दृश्यों के पीछे क्या चल रहा है।
यह system
. द्वारा किया जाता है विधि, सी में यह विधि सिर्फ आपके आदेश को /bin/sh
. पर भेजती है , जो एक शेल एप्लिकेशन है। आइए देखें कि आप किस तरह /bin/sh
को लागू कर सकते हैं रूबी में करता है।
नोट :यह केवल Linux / Mac पर काम करेगा
सिस्टम विधि:
def system(command) fork { exec(command) } end
यहाँ क्या होता है कि fork
वर्तमान प्रक्रिया की एक नई प्रतिलिपि बनाता है, फिर इस प्रक्रिया को उस कमांड से बदल दिया जाता है जिसे हम exec
के माध्यम से चलाना चाहते हैं तरीका। यह Linux प्रोग्रामिंग में एक बहुत ही सामान्य पैटर्न है।
यदि आप फोर्क नहीं करते हैं तो वर्तमान प्रक्रिया को बदल दिया जाता है, जिसका अर्थ है कि जब आप कमांड चला रहे हैं (ls
, cd
या कुछ और) किया जाता है तो आपका रूबी प्रोग्राम इसके साथ समाप्त हो जाएगा।
आप इसे यहां होते हुए देख सकते हैं:
def system(command) exec(command) end system('ls') # This code will never run! puts "after system"
निष्कर्ष
इस पोस्ट में आपने सीखा कि शेल एक REPL जैसा इंटरफ़ेस है (सोचें irb
/ pry
) आपके सिस्टम के साथ बातचीत करने के लिए। आपने शक्तिशाली Readline
. का उपयोग करके अपने स्वयं के शेल का निर्माण करना भी सीखा पुस्तकालय, जो इतिहास और स्वतः पूर्णता जैसी कई अंतर्निहित सुविधाएँ प्रदान करता है (लेकिन आपको यह परिभाषित करना होगा कि यह कैसे काम करता है)।
और उसके बाद आपने fork
. के बारे में सीखा + exec
लिनक्स प्रोग्रामिंग प्रोजेक्ट्स में आमतौर पर इस्तेमाल किया जाने वाला पैटर्न।
अगर आपको यह पोस्ट अच्छी लगी हो तो क्या आप मुझ पर एक एहसान कर सकते हैं और इसे अपने सभी रूबी दोस्तों के साथ साझा कर सकते हैं? यह ब्लॉग को बढ़ने में मदद करेगा और अधिक लोग सीख सकेंगे 🙂