description: Ruby System Shell Command Execution
Command Execution
Some things to think about when choosing between these ways are:
- Are you going to interact with none interactive shell, like
ncat
? - Do you just want stdout or do you need stderr as well? or even separated out?
- How big is your output? Do you want to hold the entire result in memory?
- Do you want to read some of your output while the subprocess is still running?
- Do you need result codes?
- 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
>> exec('date')
Sun Sep 27 00:39:22 AST 2015
RubyFu( ~ )->
Kernel#system
>> system 'date'
Sun Sep 27 00:38:01 AST 2015
#=> 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
ruby -e 'exec("/bin/sh 2>&1")'
system
ruby -e 'system("/bin/sh 2>&1")'
Kernel#` (backticks)
>> `date`
#=> "Sun Sep 27 00:38:54 AST 2015\n"
IO#popen
>> IO.popen("date") { |f| puts f.gets }
Sun Sep 27 00:40:06 AST 2015
#=> nil
Open3#popen3
require 'open3'
stdin, stdout, stderr = Open3.popen3('dc')
#=> [#<IO:fd 14>, #<IO:fd 16>, #<IO:fd 18>, #<Process::Waiter:0x00000002f68bd0 sleep>]
>> stdin.puts(5)
#=> nil
>> stdin.puts(10)
#=> nil
>> stdin.puts("+")
#=> nil
>> stdin.puts("p")
#=> nil
>> stdout.gets
#=> "15\n"
Process#spawn
Kernel.spawn executes the given command in a subshell. It returns immediately with the process id.
pid = Process.spawn("date")
Sun Sep 27 00:50:44 AST 2015
#=> 12242
%x””, %x[], %x{}, %x$’’$
>> %x"date"
#=> Sun Sep 27 00:57:20 AST 2015\n"
>> %x[date]
#=> "Sun Sep 27 00:58:00 AST 2015\n"
>> %x{date}
#=> "Sun Sep 27 00:58:06 AST 2015\n"
>> %x$'date'$
#=> "Sun Sep 27 00:58:12 AST 2015\n"
Rake#sh
require 'rake'
>> sh 'date'
date
Sun Sep 27 00:59:05 AST 2015
#=> true
Extra
To check the status of the backtick operation you can execute $?.success?
$?
>> `date`
=> "Sun Sep 27 01:06:42 AST 2015\n"
>> $?.success?
=> true
How to chose?
a great flow chart has been made on stackoverflow