How to call shell commands from Ruby

前端 未结 20 2351
旧时难觅i
旧时难觅i 2020-11-22 01:10

How do I call shell commands from inside of a Ruby program? How do I then get output from these commands back into Ruby?

20条回答
  •  一整个雨季
    2020-11-22 01:51

    Using the answers here and linked in Mihai's answer, I put together a function that meets these requirements:

    1. Neatly captures STDOUT and STDERR so they don't "leak" when my script is run from the console.
    2. Allows arguments to be passed to the shell as an array, so there's no need to worry about escaping.
    3. Captures the exit status of the command so it is clear when an error has occurred.

    As a bonus, this one will also return STDOUT in cases where the shell command exits successfully (0) and puts anything on STDOUT. In this manner, it differs from system, which simply returns true in such cases.

    Code follows. The specific function is system_quietly:

    require 'open3'
    
    class ShellError < StandardError; end
    
    #actual function:
    def system_quietly(*cmd)
      exit_status=nil
      err=nil
      out=nil
      Open3.popen3(*cmd) do |stdin, stdout, stderr, wait_thread|
        err = stderr.gets(nil)
        out = stdout.gets(nil)
        [stdin, stdout, stderr].each{|stream| stream.send('close')}
        exit_status = wait_thread.value
      end
      if exit_status.to_i > 0
        err = err.chomp if err
        raise ShellError, err
      elsif out
        return out.chomp
      else
        return true
      end
    end
    
    #calling it:
    begin
      puts system_quietly('which', 'ruby')
    rescue ShellError
      abort "Looks like you don't have the `ruby` command. Odd."
    end
    
    #output: => "/Users/me/.rvm/rubies/ruby-1.9.2-p136/bin/ruby"
    

提交回复
热议问题