Open3.popen3 or Open3.capture3:
Open3 actually just uses Ruby's spawn command, but gives you a much better API.
Open3.popen3
Popen3 runs in a sub-process and returns stdin, stdout, stderr and wait_thr.
require 'open3'
stdin, stdout, stderr, wait_thr = Open3.popen3("sleep 5s && ls")
puts "#{stdout.read} #{stderr.read} #{wait_thr.value.exitstatus}"
or
require 'open3'
cmd = 'git push heroku master'
Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
puts "stdout is:" + stdout.read
puts "stderr is:" + stderr.read
end
will output: stdout is: stderr is:fatal: Not a git repository (or any of the parent directories): .git
or
require 'open3'
cmd = 'ping www.google.com'
Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
while line = stdout.gets
puts line
end
end
will output:
Pinging www.google.com [216.58.223.36] with 32 bytes of data:
Reply from 216.58.223.36: bytes=32 time=16ms TTL=54
Reply from 216.58.223.36: bytes=32 time=10ms TTL=54
Reply from 216.58.223.36: bytes=32 time=21ms TTL=54
Reply from 216.58.223.36: bytes=32 time=29ms TTL=54
Ping statistics for 216.58.223.36:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 10ms, Maximum = 29ms, Average = 19ms
Open3.capture3:
require 'open3'
stdout, stderr, status = Open3.capture3('my_funky_command', 'and', 'some', 'argumants')
if status.success?
# command completed successfully, do some more stuff
else
raise "An error occured"
end
or
Open3.capture3('/some/binary with some args')
Not recommended though, due to additional overhead and the potential for shell injections.
If the command reads from stdin and you want to feed it some data:
Open3.capture3('my_funky_command', stdin_data: 'read from stdin')
Run the command with a different working directory, by using chdir:
Open3.capture3('my_funky_command', chdir: '/some/directory')