description: Ruby System Shell Command Execution

Command Execution

Some things to think about when choosing between these ways are:

  1. Are you going to interact with none interactive shell, like ncat ?
  2. Do you just want stdout or do you need stderr as well? or even separated out?
  3. How big is your output? Do you want to hold the entire result in memory?
  4. Do you want to read some of your output while the subprocess is still running?
  5. Do you need result codes?
  6. Do you need a ruby object that represents the process and lets you kill it on demand?

The following ways are applicable on all operating systems.

Kernel#exec

  1. >> exec('date')
  2. Sun Sep 27 00:39:22 AST 2015
  3. RubyFu( ~ )->

Kernel#system

  1. >> system 'date'
  2. Sun Sep 27 00:38:01 AST 2015
  3. #=> true

Dealing with ncat session?

If you ever wondered how to do deal with interactive command like passwd due ncat session in Ruby?. You must propuly was using python -c 'import pty; pty.spawn("/bin/sh")'
Well, in Ruby it’s really easy using exec or system. The main trick is to forward STDERR to STDOUT so you can see system errors.

exec

  1. ruby -e 'exec("/bin/sh 2>&1")'

system

  1. ruby -e 'system("/bin/sh 2>&1")'

Kernel#` (backticks)

  1. >> `date`
  2. #=> "Sun Sep 27 00:38:54 AST 2015\n"

IO#popen

  1. >> IO.popen("date") { |f| puts f.gets }
  2. Sun Sep 27 00:40:06 AST 2015
  3. #=> nil

Open3#popen3

  1. require 'open3'
  2. stdin, stdout, stderr = Open3.popen3('dc')
  3. #=> [#<IO:fd 14>, #<IO:fd 16>, #<IO:fd 18>, #<Process::Waiter:0x00000002f68bd0 sleep>]
  4. >> stdin.puts(5)
  5. #=> nil
  6. >> stdin.puts(10)
  7. #=> nil
  8. >> stdin.puts("+")
  9. #=> nil
  10. >> stdin.puts("p")
  11. #=> nil
  12. >> stdout.gets
  13. #=> "15\n"

Process#spawn

Kernel.spawn executes the given command in a subshell. It returns immediately with the process id.

  1. pid = Process.spawn("date")
  2. Sun Sep 27 00:50:44 AST 2015
  3. #=> 12242

%x””, %x[], %x{}, %x$’’$

  1. >> %x"date"
  2. #=> Sun Sep 27 00:57:20 AST 2015\n"
  3. >> %x[date]
  4. #=> "Sun Sep 27 00:58:00 AST 2015\n"
  5. >> %x{date}
  6. #=> "Sun Sep 27 00:58:06 AST 2015\n"
  7. >> %x$'date'$
  8. #=> "Sun Sep 27 00:58:12 AST 2015\n"

Rake#sh

  1. require 'rake'
  2. >> sh 'date'
  3. date
  4. Sun Sep 27 00:59:05 AST 2015
  5. #=> true

Extra

To check the status of the backtick operation you can execute $?.success?

$?

  1. >> `date`
  2. => "Sun Sep 27 01:06:42 AST 2015\n"
  3. >> $?.success?
  4. => true

How to chose?

a great flow chart has been made on stackoverflow
Command Execution - 图1