How to call shell commands from Ruby

前端 未结 20 2012
旧时难觅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:42

    Given a command like attrib:

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

    I've found that while this method isn't as memorable as

    system("thecommand")
    

    or

    `thecommand`
    

    in backticks, a good thing about this method compared to other methods is backticks don't seem to let me puts the command I run/store the command I want to run in a variable, and system("thecommand") doesn't seem to let me get the output whereas this method lets me do both of those things, and it lets me access stdin, stdout and stderr independently.

    See "Executing commands in ruby" and Ruby's Open3 documentation.

    0 讨论(0)
  • 2020-11-22 01:45

    Here's the best article in my opinion about running shell scripts in Ruby: "6 Ways to Run Shell Commands in Ruby".

    If you only need to get the output use backticks.

    I needed more advanced stuff like STDOUT and STDERR so I used the Open4 gem. You have all the methods explained there.

    0 讨论(0)
  • 2020-11-22 01:45

    One more option:

    When you:

    • need stderr as well as stdout
    • can't/won't use Open3/Open4 (they throw exceptions in NetBeans on my Mac, no idea why)

    You can use shell redirection:

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

    The 2>&1 syntax works across Linux, Mac and Windows since the early days of MS-DOS.

    0 讨论(0)
  • 2020-11-22 01:46

    The easiest way is, for example:

    reboot = `init 6`
    puts reboot
    
    0 讨论(0)
  • 2020-11-22 01:47

    If you really need Bash, per the note in the "best" answer.

    First, note that when Ruby calls out to a shell, it typically calls /bin/sh, not Bash. Some Bash syntax is not supported by /bin/sh on all systems.

    If you need to use Bash, insert bash -c "your Bash-only command" inside of your desired calling method:

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

    To test:

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

    Or if you are running an existing script file like

    script_output = system("./my_script.sh")
    

    Ruby should honor the shebang, but you could always use

    system("bash ./my_script.sh")
    

    to make sure, though there may be a slight overhead from /bin/sh running /bin/bash, you probably won't notice.

    0 讨论(0)
  • 2020-11-22 01:47

    This is not really an answer but maybe someone will find it useful:

    When using TK GUI on Windows, and you need to call shell commands from rubyw, you will always have an annoying CMD window popping up for less then a second.

    To avoid this you can use:

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

    or

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

    Both will store the ipconfig output inside log.txt, but no windows will come up.

    You will need to require 'win32ole' inside your script.

    system(), exec() and spawn() will all pop up that annoying window when using TK and rubyw.

    0 讨论(0)
提交回复
热议问题