2011-06-14 18 views
312

निम्नलिखित रूबी विधियों के बीच क्या अंतर है?रूबी, निष्पादन, सिस्टम और% x() या बैकटिक्स के बीच अंतर

exec, system और %x() या बैकटिक

मैं वे टर्मिनल रूबी के माध्यम से प्रोग्राम के रूप में आदेश पर अमल करने के लिए उपयोग किया जाता है पता है, लेकिन मुझे पता है कि यही कारण है कि यह करने के लिए तीन अलग-अलग तरीके हैं चाहते हैं।

+5

के बाद से किसी को सिर्फ इस पुराने धागे अप खोदा, "यूनिक्स प्रक्रियाओं के साथ काम करना" विषय में रुचि रखते Rubyists के लिए एक शानदार किताब है: http://workingwithunixprocesses.com/ –

+0

वहाँ एक महान रूबी है उस विषय पर क्विकटिप्स आलेख: [खोल आदेश निष्पादित करें] (http://rubyquicktips.com/post/5862861056/execute-shell-commands)। –

+1

ये आदेश, और कई अन्य, दस्तावेज़ों में काफी अच्छी तरह से समझाए गए हैं: [exec] (http://www.ruby-doc.org/core/Kernel.html#method-i-exec) [system] (http: //www.ruby-doc.org/core/Kernel.html#method-i-system) [बैकटिक्स] (http://www.ruby-doc.org/core/Kernel.html#method-i-60) – zetetic

उत्तर

339

प्रणाली

system विधि एक प्रणाली कार्यक्रम कहता है। आपको इस विधि को स्ट्रिंग तर्क के रूप में कमांड प्रदान करना होगा। उदाहरण के लिए:

>> system("date") 
Wed Sep 4 22:03:44 CEST 2013 
=> true 

लागू कार्यक्रम अपने रूबी कार्यक्रम की वर्तमान STDIN, STDOUT और STDERR वस्तुओं का प्रयोग करेंगे। वास्तव में, वास्तविक वापसी मूल्य या तो true, false या nil है। उदाहरण में दिनांक STDIN के आईओ ऑब्जेक्ट के माध्यम से मुद्रित किया गया था। यदि प्रक्रिया शून्य स्थिति के साथ निकलती है, तो false प्रक्रिया समाप्त होने पर प्रक्रिया निष्पादन विफल होने पर nil से बाहर निकलने पर विधि true वापस आ जाएगी।

एक और दुष्प्रभाव यह है कि वैश्विक चर $?Process::Status ऑब्जेक्ट पर सेट है। इस ऑब्जेक्ट में कॉल के बारे में जानकारी होगी, जिसमें आवंटित प्रक्रिया की प्रक्रिया पहचानकर्ता (पीआईडी) और निकास स्थिति शामिल है।

>> system("date") 
Wed Sep 4 22:11:02 CEST 2013 
=> true 
>> $? 
=> #<Process::Status: pid 15470 exit 0> 

बैकटिक

Backticks (``) एक प्रणाली कार्यक्रम फोन और इसके उत्पादन लौट आते हैं। पहले दृष्टिकोण के विपरीत, आदेश एक स्ट्रिंग के माध्यम से प्रदान नहीं किया जाता है, लेकिन इसे बैकटिक्स जोड़ी के अंदर डालकर।

>> `date` 
=> Wed Sep 4 22:22:51 CEST 2013 

वैश्विक चर $? भी बैकटिक के माध्यम से स्थापित किया जाएगा। बैकटीक्स के साथ आप स्ट्रिंग इंटरपोलेशन का उपयोग भी कर सकते हैं।

% x()

%x का उपयोग बैकटिक शैली के लिए एक विकल्प है। यह आउटपुट भी वापस कर देगा। अपने रिश्तेदारों की तरह %w और %q (दूसरों के बीच), किसी भी डिलीमीटर को तब तक पर्याप्त होगा जब तक ब्रैकेट-शैली डिलीमीटर मिलेंगे। इसका मतलब है %x(date), %x{date} और %x-date- सभी समानार्थी शब्द हैं। बैकटिक्स की तरह %x स्ट्रिंग इंटरपोलेशन का उपयोग कर सकते हैं।

कार्यकारी

Kernel#exec वर्तमान प्रक्रिया (आपका रूबी स्क्रिप्ट) का उपयोग करके प्रक्रिया exec के माध्यम से लागू साथ बदल दिया है। विधि तर्क के रूप में एक स्ट्रिंग ले सकते हैं। इस मामले में स्ट्रिंग शैल विस्तार के अधीन होगी। एक से अधिक तर्कों का उपयोग करते समय, पहले प्रोग्राम को निष्पादित करने के लिए उपयोग किया जाता है और निम्नलिखित को प्रोग्राम के लिए तर्क के रूप में प्रदान किया जाता है।

Open3.popen3

कभी कभी आवश्यक जानकारी मानक इनपुट या मानक त्रुटि के लिए लिखा है और आप उन पर नियंत्रण पाने के लिए और साथ ही जरूरत है। यहाँ Open3.popen3 काम में आता:

require 'open3' 

Open3.popen3("curl http://example.com") do |stdin, stdout, stderr, thread| 
    pid = thread.pid 
    puts stdout.read.chomp 
end 
+1

और 'एसटीडीआईएन', 'एसटीडीओआरटी', 'एसटीडीईआरआर' को संभालने के तरीके के बारे में अधिक सुदृढ़ नियंत्रण के लिए, 'ओपन 3.popen3' पर विचार करें; जैसे http://stackoverflow.com/a/10922097/258662 – cboettig

+1

@platzhirsch - बहुत अच्छी तरह से समझाया गया देखें। धन्यवाद। – itsh

+0

धन्यवाद, जोड़ा गया। @cboettig –

91

वे अलग-अलग चीजें करते हैं। exec नई प्रक्रिया के साथ वर्तमान प्रक्रिया को प्रतिस्थापित करता है और कभी नहीं लौटाता है। system एक और प्रक्रिया का आह्वान करता है और वर्तमान प्रक्रिया में इसके बाहर निकलने के मूल्य देता है। बैकटीक्स का उपयोग करना एक और प्रक्रिया का आह्वान करता है और उस प्रक्रिया के आउटपुट को वर्तमान प्रक्रिया में देता है।

176

यहाँ एक प्रवाह संचित्र this answer पर आधारित है। यह भी देखें, using script to emulate a terminal

enter image description here

+1

यह इतना आसान नहीं है। मेरे मामले में यह "प्रक्रिया पूरी होने तक अवरुद्ध करने के लिए ठीक था (और आवश्यकता है)" फिर STDOUT/STDERR आउटपुट की जांच करने के लिए popen3 का उपयोग करें। – Nakilon

+0

आप हमेशा एक लूपिंग में इसे लपेटकर एक गैर-अवरुद्ध कॉल (प्रभावी रूप से) ब्लॉक कर सकते हैं। आप एक गैर-अवरुद्ध कॉल में आसानी से अवरुद्ध कॉल नहीं कर सकते हैं। – Ian

संबंधित मुद्दे