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

रूबी के माध्यम से शेल कमांड से स्टडआउट और स्टैडर कैप्चर करना

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

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

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

exec("echo 'hello world'") # exits from ruby, then runs the command
system('echo', 'hello world') # returns the status code
sh('echo', 'hello world') # returns the status code
`echo "hello world"` # returns stdout
%x[echo 'hello world'] # returns stdout

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

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

Open3

अजीब तरह से नामित ओपन3 मॉड्यूल रूबी के मानक पुस्तकालय का हिस्सा है। यह क्या करता है?

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

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

capture3

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

आइए एक उदाहरण देखें। मान लीजिए कि आप अपनी वर्तमान निर्देशिका में फ़ाइलों की एक सूची प्राप्त करना चाहते हैं। ऐसा करने के लिए आप 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

हुड के तहत, कैप्चर 3 एक अधिक शक्तिशाली विधि का उपयोग करता है जिसे पॉपेन 3 कहा जाता है। यह विधि सिस्टम () जैसे अधिक परिचित तरीकों की तुलना में थोड़ा अलग तरीके से काम करती है।

यह इस तरह दिखता है:

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 पर बंद करना होगा।)

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

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

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

थ्रेड्स

एक तर्क है जिसके बारे में हमने अभी तक बात नहीं की है। वह धागा है।

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

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

  • 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") {|मैं, ओ, ई, टी| o.read } गतिरोध यदि प्रोग्राम stderr पर बहुत अधिक आउटपुट उत्पन्न करता है। आपको एक साथ stdout और stderr पढ़ना चाहिए (थ्रेड्स या IO.select का उपयोग करके)। हालाँकि, यदि आपको stderr आउटपुट की आवश्यकता नहीं है, तो आप [::popen2](https://ruby-doc.org/stdlib-2.1.0/libdoc/open3/rdoc/Open3.html#method-c- का उपयोग कर सकते हैं। पॉपन 2)। यदि मर्ज किए गए 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 पर विचार कर सकते हैं। -कैप्चर 3)।

  1. रूबी से फिडल के माध्यम से किसी भी सी पुस्तकालय का प्रयोग करें - रूबी मानक पुस्तकालय सबसे अच्छा गुप्त रखा जाता है।

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

  1. रूबी में खरोंच से एक साधारण वेबसोकेट सर्वर का निर्माण

    वेबसोकेट इन दिनों अधिक से अधिक प्रेस हो रहे हैं। हम सुनते हैं कि वे भविष्य हैं। हमने सुना है कि रेल 5 में एक्शनकेबल के लिए उनका उपयोग करना पहले से कहीं अधिक आसान है। लेकिन वास्तव में वेबसोकेट क्या हैं? वे कैसे काम करते हैं? इस पोस्ट में हम रूबी में स्क्रैच से एक साधारण वेबसॉकेट सर्वर बनाकर इन सवालो

  1. कैसे HTTP शीर्षलेख nginx से आपके रूबी ऐप में पास हो जाते हैं

    इन दिनों लगभग सभी वेब डेवलपमेंट फ्रेमवर्क के साथ किए जाते हैं। चाहे आप रेल, सिनात्रा, या लोटस का उपयोग करें, आपको वास्तव में यह सोचने की ज़रूरत नहीं है कि कुकीज और अन्य शीर्षलेख nginx या apache से, एप्लिकेशन सर्वर और आपके ऐप में कैसे जाते हैं। वे बस करते हैं। हम इस यात्रा की थोड़ी और गहराई से जाँच