Computer >> कंप्यूटर ट्यूटोरियल >  >> प्रोग्रामिंग >> Ruby

Ruby में शेल कमांड के STDOUT, STDERR, और एग्जिट स्टेटस को कैप्चर करना

tl;dr यदि आप Ruby से शेल कमांड चलाना चाहते हैं और उसका stdout, stderr और रिटर्न स्टेटस कैप्चर करना चाहते हैं, तो `Open3.capture3` मेथड देखें। यदि आप stdout और stderr डेटा को स्ट्रीमिंग फैशन में प्रोसेस करना चाहते हैं, तो `Open3.popen3` देखें।

इतने सारे खराब विकल्प

Ruby से शेल कमांड निष्पादित करने के सचमुच 492 तरीके हैं और उनमें से प्रत्येक थोड़ा अलग तरीके से काम करता है। मुझे यकीन है कि आपने नीचे दिए गए दृष्टिकोणों में से एक का उपयोग किया है। मेरा गो-टू हमेशा बैक-टिक्स (``) रहा है।

exec("echo 'hello world'") # Ruby से बाहर निकलता है, फिर कमांड चलाता है system('echo', 'hello world') # स्टेटस कोड लौटाता है sh('echo', 'hello world') # स्टेटस कोड लौटाता है `echo "hello world"` # stdout लौटाता है %x[echo 'hello world'] # stdout लौटाता है 

लेकिन ये दृष्टिकोण काफी सीमित हैं। मान लीजिए कि आपको न केवल अपने शेल कमांड का stdout, बल्कि उसका stderr भी कैप्चर करने की आवश्यकता है। आप बस भाग्य से बाहर हैं। या मान लीजिए आप कमांड समाप्त होने पर एक बार में सभी के बजाय, stdout डेटा को एक स्ट्रीम में प्रोसेस करना चाहेंगे? भाग्य से बाहर।

एक और विकल्प है। एक जो आपको कमांड को एसिंक्रोनस रूप से चलाने की क्षमता देता है, और जो आपको stdout, stderr, एग्जिट कोड, और PIDs देता है। आइए इसे देखें!

Open3

अजीब नाम वाला open3 मॉड्यूल Ruby की मानक लाइब्रेरी का हिस्सा है। यह क्या करता है?

Open3 आपको किसी अन्य प्रोग्राम को चलाते समय stdout, stderr, एग्जिट कोड और चाइल्ड प्रोसेस की प्रतीक्षा करने के लिए एक थ्रेड तक पहुंच प्रदान करता है। आप प्रोग्राम के विभिन्न एट्रिब्यूट्स, रीडायरेक्शन, वर्तमान निर्देशिका, आदि को उसी तरह निर्दिष्ट कर सकते हैं जैसे Process.spawn के लिए। (_स्रोत: [Open3 Docs](https://ruby-doc.org/stdlib-2.1.0/libdoc/open3/rdoc/Open3.html))_

कभी उपयोग नहीं किया? कभी इसके बारे में सुना भी नहीं? मुझे लगता है कि ऐसा इसलिए है क्योंकि यह सबसे दोस्ताना लाइब्रेरी के रूप में सामने नहीं आता। नाम ही C की तुलना में Ruby की तरह कम लगता है। और दस्तावेज़ीकरण काफी हार्ड-कोर नेक-बियर्ड है। लेकिन एक बार जब आप इसे आजमाते हैं, तो आप पाएंगे कि यह उतना डराने वाला नहीं है जितना लगता है।

capture3

क्या होगा यदि stdout, stderr AND स्टेटस कोड को कैप्चर करने का एक आसान तरीका होता? खैर, है। यदि आपके पास इस आर्टिकल के बाकी हिस्से को पढ़ने का समय नहीं है, तो बस जान लें कि आप `capture3` नामक एक मेथड का उपयोग कर सकते हैं और इसे एक दिन कह सकते हैं।

आइए एक उदाहरण देखें। मान लीजिए आप अपने वर्तमान निर्देशिका में फ़ाइलों की सूची प्राप्त करना चाहते हैं। ऐसा करने के लिए आप `ls` कमांड चला सकते हैं।

यदि आप बैक-टिक सिंटैक्स का उपयोग करते तो यह ऐसा दिखता:

puts(`ls`) 

`capture3` के साथ यह ऐसा दिखता है:

require 'open3' stdout, stderr, status = Open3.capture3("ls") 

यह आपकी कमांड चलाएगा और आपको stdout और stderr को स्ट्रिंग के रूप में देगा। ना कोई झंझट ना कोई उपद्रव।

सुरक्षा

आप आमतौर पर अपने उपयोगकर्ताओं को अपने वेब सर्वर पर मनमाने कमांड चलाने की क्षमता नहीं देना चाहते। इसलिए `identify #{ params[:filename] }` जैसा कोड इतना भयानक विचार है।

Open3 आपको कमांड को डेटा से अलग करके ऐसी समस्याओं से बचने देता है। यह सिस्टम मेथड की तरह ही काम करता है।

Open3.capture3("identify", params[:filename], other_unsafe_params) 

popen3

हुड के तहत, capture3 एक बहुत अधिक शक्तिशाली मेथड का उपयोग करता है जिसे popen3 कहा जाता है। यह मेथड system() जैसे अधिक परिचित मेथड्स से थोड़ा अलग काम करता है।

यहाँ देखें कि यह कैसा दिखता है:

require 'open3' Open3.popen3("ls") do |stdout, stderr, status, thread| puts stdout.read end 

यह कुछ वैसा ही है जैसे जब आप एक फ़ाइल खोलते हैं और उससे पढ़ते हैं। मुझे यकीन है कि आपने ऐसा कोड देखा होगा:

File.open("my/file/path", "r") do |f| puts f.read end 

पाइप्स

Open3 के साथ, stdout और stderr सभी पाइप हैं, जो फ़ाइल बफर की तरह व्यवहार करते हैं। और फ़ाइलों की तरह, जब आप उनके साथ काम कर लें तो उन्हें बंद करने की आवश्यकता होती है। यही ब्लॉक सिंटैक्स का कारण है। (एक नॉन-ब्लॉक सिंटैक्स है, लेकिन आपको मैन्युअल रूप से stdout, और stderr पर क्लोज कॉल करना होगा।)

`read` मेथड पाइप बंद होने तक प्रतीक्षा करता है और फिर एक मान लौटाता है। लेकिन पाइप्स लाइनों को पढ़ने का भी समर्थन करते हैं जैसे ही वे उपलब्ध होते हैं। कल्पना करें कि आपका शेल कमांड चलने में कुछ सेकंड लेता है। उस दौरान, यह stderr पर एक स्टेटस मैसेज प्रिंट कर रहा है। आप उसे कैप्चर करना चाहेंगे और अपने उपयोगकर्ताओं को प्रदर्शित करेंगे।

यहाँ बताया गया है कि आप stderr को एक बार में एक लाइन कैसे कैप्चर करेंगे।

require 'open3' Open3.popen3("sleep 2; ls") do |stdout, stderr, status, thread| while line=stderr.gets do puts(line) end end 

थ्रेड्स

एक आर्गुमेंट है जिसके बारे में हमने बात नहीं की है। वह है थ्रेड।

थ्रेड आर्गुमेंट आपको एक Ruby थ्रेड का संदर्भ देता है जो आपकी कमांड के समाप्त होने की प्रतीक्षा कर रहा है। अब, कमांड थ्रेड में नहीं चल रहा है। यह पूरी तरह से अलग प्रक्रिया में चल रहा है। थ्रेड बस प्रक्रिया को देखता है और तब तक प्रतीक्षा करता है जब तक यह पूरा नहीं हो जाता।

आप उस थ्रेड संदर्भ से कुछ उपयोगी डेटा प्राप्त कर सकते हैं।

  • thread.pid - आपके शेल कमांड की प्रक्रिया आईडी रखता है। आपको इसकी आवश्यकता होगी यदि आप उस प्रक्रिया के खिलाफ अतिरिक्त OS-स्तरीय ऑपरेशन करना चाहते थे।

  • thread.status - प्रक्रिया का एग्जिट स्टेटस रखता है। सफलता या विफलता के लिए 1 या 0।

चेतावनी

Open3 डॉक्स से:

आपको डेडलॉक से बचने के लिए सावधान रहना चाहिए। चूंकि पाइप निश्चित लंबाई के बफर हैं, [::popen3](https://ruby-doc.org/stdlib-2.1.0/libdoc/open3/rdoc/Open3.html#method-c-popen3)("prog") {|i, o, e, t| o.read } डेडलॉक होता है यदि प्रोग्राम stderr पर बहुत अधिक आउटपुट उत्पन्न करता है। आपको stdout और stderr को एक साथ पढ़ना चाहिए (थ्रेड्स या IO.select का उपयोग करके)। हालांकि, यदि आपको stderr आउटपुट की आवश्यकता नहीं है, तो आप [::popen2](https://ruby-doc.org/stdlib-2.1.0/libdoc/open3/rdoc/Open3.html#method-c-popen2) का उपयोग कर सकते हैं। यदि मर्ज किया गया stdout और stderr आउटपुट कोई समस्या नहीं है, तो आप [::popen2e](https://ruby-doc.org/stdlib-2.1.0/libdoc/open3/rdoc/Open3.html#method-c-popen2e) का उपयोग कर सकते हैं। यदि आपको वास्तव में stdout और stderr आउटपुट को अलग स्ट्रिंग के रूप में चाहिए, तो आप [::capture3](https://ruby-doc.org/stdlib-2.1.0/libdoc/open3/rdoc/Open3.html#method-c-capture3) पर विचार कर सकते हैं।

  1. Fiddle के साथ Ruby से किसी भी C लाइब्रेरी तक पहुंचें: Ruby की छिपी क्षमताओं को अनलॉक करें Fiddle के साथ Ruby से किसी भी C लाइब्रेरी तक पहुंचें: Ruby की छिपी क्षमताओं को अनलॉक करें

    Fiddle एक कम ज्ञात मॉड्यूल है जिसे Ruby की मानक लाइब्रेरी में 1.9.x में जोड़ा गया था। यह आपको Ruby से सीधे C लाइब्रेरी के साथ बातचीत करने की अनुमति देता है। यह आपको रनटाइम पर Ruby इंटरप्रेटर का निरीक्षण और परिवर्तन करने भी देता है। यह libffi को रैप करके काम करता है, एक लोकप्रिय C लाइब्रेरी जो एक भाष

  1. स्क्रैच से Ruby WebSocket सर्वर बनाएं: चरण-दर-चरण मार्गदर्शिका स्क्रैच से Ruby WebSocket सर्वर बनाएं: चरण-दर-चरण मार्गदर्शिका

    आजकल WebSockets को काफी चर्चा मिल रही है। हम सुनते हैं कि वे भविष्य हैं। हम सुनते हैं कि Rails 5 में ActionCable की बदौलत उनका उपयोग पहले से आसान हो गया है। लेकिन वास्तव में WebSockets क्या हैं? वे कैसे काम करते हैं? इस पोस्ट में हम एक साधारण WebSocket सर्वर को Ruby में स्क्रैच से बनाकर इन सवालों क

  1. Nginx कैसे आपके Ruby ऐप को HTTP हेडर्स भेजता है: एक स्पष्ट, पेशेवर गाइड Nginx कैसे आपके Ruby ऐप को HTTP हेडर्स भेजता है: एक स्पष्ट, पेशेवर गाइड

    आजकल लगभग सभी वेब डेवलपमेंट फ्रेमवर्क के साथ किया जाता है। चाहे आप Rails, Sinatra, या Lotus का उपयोग करें, आपको वास्तव में यह सोचने की ज़रूरत नहीं है कि कुकीज़ और अन्य हेडर्स Nginx या Apache से एप्लिकेशन सर्वर और फिर आपके ऐप तक कैसे पहुँचते हैं। वे बस पहुँच जाते हैं। HTTP हेडर्स क्या हैं? जब भी कोई