ruby - रूबी से शेल कमांड को कॉल करना




shell interop (14)

आप पर्ल के समान बैकटिक ऑपरेटर (`) का भी उपयोग कर सकते हैं:

directoryListing = `ls /`
puts directoryListing # prints the contents of the root directory

आसान अगर आपको कुछ आसान चाहिए।

आप किस विधि का उपयोग करना चाहते हैं यह ठीक उसी पर निर्भर करता है जिसे आप पूरा करने की कोशिश कर रहे हैं; विभिन्न तरीकों के बारे में अधिक जानकारी के लिए डॉक्स जांचें।

मैं रूबी प्रोग्राम के अंदर से शेल कमांड कैसे कह सकता हूं? फिर मैं रूबी में इन कमांड से आउटपुट कैसे प्राप्त करूं?


इन तंत्रों के बीच चयन करते समय सोचने वाली कुछ बातें हैं:

  1. क्या आप सिर्फ stdout चाहते हैं या आपको stderr की भी आवश्यकता है? या यहां तक ​​कि अलग हो गए?
  2. आपका आउटपुट कितना बड़ा है? क्या आप पूरे परिणाम को स्मृति में रखना चाहते हैं?
  3. क्या आप अपने कुछ आउटपुट पढ़ना चाहते हैं जबकि सबप्रोसेस अभी भी चल रहा है?
  4. क्या आपको परिणाम कोड की आवश्यकता है?
  5. क्या आपको एक माणिक वस्तु की आवश्यकता है जो प्रक्रिया का प्रतिनिधित्व करती है और आपको मांग पर मार देती है?

आपको साधारण बैकटिक्स (``), सिस्टम (), और IO.popen से लेकर IO.pipe और IO.select साथ IO.pipe / IO.select . IO.select

यदि आप एक सबप्रोसेस को निष्पादित करने में बहुत लंबा समय लगाते हैं, तो आप मिश्रण में टाइमआउट फेंकना चाहते हैं।

दुर्भाग्य से, यह बहुत निर्भर करता है


एक और विकल्प:

जब आप:

  • stderr के साथ ही stdout की जरूरत है
  • Open3 / Open4 का उपयोग नहीं कर सकते हैं (वे मेरे मैक पर NetBeans में अपवाद फेंकते हैं, पता नहीं क्यों)

आप शेल पुनर्निर्देशन का उपयोग कर सकते हैं:

puts %x[cat bogus.txt].inspect
  => ""

puts %x[cat bogus.txt 2>&1].inspect
  => "cat: bogus.txt: No such file or directory\n"

MS-DOS के शुरुआती दिनों से 2>&1 सिंटैक्स Linux , मैक और Windows काम करता है।


एक कमांड दिया गया है जैसे अट्रिब

require 'open3'

a="attrib"
Open3.popen3(a) do |stdin, stdout, stderr|
  puts stdout.read
end

मैंने पाया है कि जबकि यह विधि उदाहरण के लिए यादगार नहीं है, उदाहरण के लिए सिस्टम ("thecommand") या backticks में thecommand, अन्य विधियों की तुलना में इस विधि के बारे में एक अच्छी बात है .. जैसे कि backticks मुझे 'डालता नहीं है। 'जिस कमांड को मैं एक वेरिएबल में चलाना चाहता हूं, उस कमांड को रन / स्टोर करता है, और सिस्टम ("thecommand") मुझे आउटपुट प्राप्त करने की अनुमति नहीं देता है। जबकि यह तरीका मुझे उन दोनों चीजों को करने देता है, और यह मुझे स्वतंत्र रूप से स्टड, स्टडआउट और स्टेडर तक पहुंचने देता है।

https://blog.bigbinary.com/2012/10/18/backtick-system-exec-in-ruby.html

http://ruby-doc.org/stdlib-2.4.1/libdoc/open3/rdoc/Open3.html


निर्दिष्ट कमांड को निष्पादित करने के लिए एक पृष्ठभूमि प्रक्रिया बनाने के लिए spawn कमांड को मत भूलना। तुम भी Process वर्ग और लौटे pid का उपयोग कर इसके पूरा होने की प्रतीक्षा कर सकते हैं:

pid = spawn("tar xf ruby-2.0.0-p195.tar.bz2")
Process.wait pid

pid = spawn(RbConfig.ruby, "-eputs'Hello, world!'")
Process.wait pid

डॉक्टर कहते हैं: यह तरीका # सिस्टम के समान है लेकिन यह कमांड के खत्म होने का इंतजार नहीं करता है।


मेरा पसंदीदा Open3

  require "open3"

  Open3.popen3('nroff -man') { |stdin, stdout, stderr| ... }

यदि आपके पास सामान्य मामले की तुलना में अधिक जटिल मामला है (जिसे `` साथ संभाला नहीं जा सकता है) तो here Kernel.spawn() । यह स्टॉक रूबी द्वारा बाहरी आदेशों को निष्पादित करने के लिए प्रदान किया गया सबसे सामान्य / पूर्ण-विशेषताओं वाला प्रतीत होता है।

जैसे आप इसका उपयोग कर सकते हैं:

  • प्रक्रिया समूह बनाएँ (Windows)
  • फ़ाइलों / प्रत्येक-दूसरे के लिए, बाहर, त्रुटि को पुनर्निर्देशित करें।
  • env var, umask सेट करें
  • कमांड निष्पादित करने से पहले dir बदलें
  • CPU / डेटा / के लिए संसाधन सीमाएँ सेट करें ...
  • वह सब करें जो अन्य उत्तरों में अन्य विकल्पों के साथ किया जा सकता है, लेकिन अधिक कोड के साथ।

आधिकारिक here पर्याप्त अच्छे उदाहरण हैं।

env: hash
  name => val : set the environment variable
  name => nil : unset the environment variable
command...:
  commandline                 : command line string which is passed to the standard shell
  cmdname, arg1, ...          : command name and one or more arguments (no shell)
  [cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
options: hash
  clearing environment variables:
    :unsetenv_others => true   : clear environment variables except specified by env
    :unsetenv_others => false  : dont clear (default)
  process group:
    :pgroup => true or 0 : make a new process group
    :pgroup => pgid      : join to specified process group
    :pgroup => nil       : dont change the process group (default)
  create new process group: Windows only
    :new_pgroup => true  : the new process is the root process of a new process group
    :new_pgroup => false : dont create a new process group (default)
  resource limit: resourcename is core, cpu, data, etc.  See Process.setrlimit.
    :rlimit_resourcename => limit
    :rlimit_resourcename => [cur_limit, max_limit]
  current directory:
    :chdir => str
  umask:
    :umask => int
  redirection:
    key:
      FD              : single file descriptor in child process
      [FD, FD, ...]   : multiple file descriptor in child process
    value:
      FD                        : redirect to the file descriptor in parent process
      string                    : redirect to file with open(string, "r" or "w")
      [string]                  : redirect to file with open(string, File::RDONLY)
      [string, open_mode]       : redirect to file with open(string, open_mode, 0644)
      [string, open_mode, perm] : redirect to file with open(string, open_mode, perm)
      [:child, FD]              : redirect to the redirected file descriptor
      :close                    : close the file descriptor in child process
    FD is one of follows
      :in     : the file descriptor 0 which is the standard input
      :out    : the file descriptor 1 which is the standard output
      :err    : the file descriptor 2 which is the standard error
      integer : the file descriptor of specified the integer
      io      : the file descriptor specified as io.fileno
  file descriptor inheritance: close non-redirected non-standard fds (3, 4, 5, ...) or not
    :close_others => false : inherit fds (default for system and exec)
    :close_others => true  : dont inherit (default for spawn and IO.popen)

यदि आपको वास्तव में "सर्वश्रेष्ठ" उत्तर में नोट के अनुसार बैश की आवश्यकता है।

सबसे पहले, ध्यान दें कि जब रूबी एक शेल को कॉल करती है, तो यह आम तौर पर बैश नहीं , /bin/sh कॉल करता है। सभी सिस्टम पर कुछ बैश सिंटैक्स /bin/sh द्वारा समर्थित नहीं है।

यदि आपको बैश का उपयोग करने की आवश्यकता है, तो अपने इच्छित कॉलिंग पद्धति के अंदर bash -c "your Bash-only command" डालें।

quick_output = system("ls -la")

quick_bash = system("bash -c 'ls -la'")

परीक्षा करना:

system("echo $SHELL") system('bash -c "echo $SHELL"')

या यदि आप एक मौजूदा स्क्रिप्ट फ़ाइल (उदाहरण के लिए script_output = system("./my_script.sh") चला रहे हैं तो रूबी को script_output = system("./my_script.sh") सम्मान करना चाहिए , लेकिन आप हमेशा सुनिश्चित करने के लिए system("bash ./my_script.sh") का उपयोग कर सकते हैं ( हालांकि, /bin/sh चल /bin/bash से एक मामूली ओवरहेड हो सकता है, आप शायद नोटिस नहीं करेंगे।


यहाँ एक अच्छा है जिसे मैं OS X पर एक रूबी स्क्रिप्ट में उपयोग करता हूं (ताकि मैं एक स्क्रिप्ट शुरू कर सकूं और खिड़की से दूर जाने के बाद भी अपडेट प्राप्त कर सकूं):

cmd = %Q|osascript -e 'display notification "Server was reset" with title "Posted Update"'|
system ( cmd )


यहाँ रूबी में शेल स्क्रिप्ट चलाने के बारे में मेरी राय में सबसे अच्छा लेख है: " http://tech.natemurray.com/2007/03/ruby-shell-commands.html "।

यदि आपको केवल आउटपुट का उपयोग करने के लिए बैकटिक्स की आवश्यकता है।

मुझे STDOUT और STDERR जैसे अधिक उन्नत सामान की आवश्यकता थी इसलिए मैंने Open4 रत्न का उपयोग किया। आपके पास वहां बताए गए सभी तरीके हैं।


वास्तव में उत्तर नहीं है, लेकिन शायद किसी को यह उपयोगी लगेगा, और इसके संबंध में।

विंडोज पर TK GUI का उपयोग करते समय, और आपको रूबी से शेल कमांड को कॉल करने की आवश्यकता होती है, यू हमेशा एक कष्टप्रद cmd विंडो को कम से कम एक सेकंड के लिए पॉपिंग करता है।

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

WIN32OLE.new('Shell.Application').ShellExecute('ipconfig > log.txt','','','open',0)

या

WIN32OLE.new('WScript.Shell').Run('ipconfig > log.txt',0,0)

दोनों ipconfig के आउटपुट को 'log.txt' के अंदर स्टोर करेंगे, लेकिन कोई विंडो नहीं आएगी।

U को आपकी स्क्रिप्ट के अंदर require 'win32ole'

system() , exec() और spawn() टीके और रूबी का उपयोग करते समय सभी उस कष्टप्रद विंडो को पॉप अप करेंगे।


हम इसे कई तरीकों से हासिल कर सकते हैं।

Kernel#exec का उपयोग करते हुए, इस कमांड के निष्पादित होने के बाद कुछ भी नहीं:

exec('ls ~')

backticks or %x का उपयोग करना

`ls ~`
=> "Applications\nDesktop\nDocuments"
%x(ls ~)
=> "Applications\nDesktop\nDocuments"

Kernel#system कमांड का उपयोग करते हुए, यदि सफल विफल होता है, तो असफल हो जाता है, यदि असफल हो जाता है और कमांड निष्पादन में विफल होने पर nil लौटाता है:

system('ls ~')
=> true

  • माणिक से शेल कमांड को कॉल करने के लिए बैकटिक्स `विधि सबसे आसान है। यह शेल कमांड का परिणाम देता है।

     url_request = 'http://google.com'
     result_of_shell_command = `curl #{url_request}`





interop