Last Updated: February 25, 2016
·
3.292K
· paulspringett

Handling sub-processes in Ruby

One of the most complete ways to handle sub-processes in Ruby is using Open3, part of the Ruby standard library.

Open3 provides various methods and options for interacting with sub-processes. Here we look at popen3, which provides access to 3 IO streams for STDIN, STDOUT and STDERR as well as a "wait thread" which references the PID of the spawned sub-process.

First require Open3

require 'open3'

Example of output on STDOUT

stdin, stdout, stderr, wait_thr = Open3.popen3('date')
=> [#<IO:fd 34>, #<IO:fd 36>, #<IO:fd 38>, #<Thread:0x007fdd690dd7b8 sleep>]

stdout.gets
=> "Wed  1 May 2013 21:42:25 BST\n"

stderr.gets
=> nil

wait_thr.pid
=> 12345

stdin.close
stdout.close
stderr.close

Example of output to STDERR

stdin, stdout, stderr, wait_thr = Open3.popen3('date --fail')
=> [#<IO:fd 34>, #<IO:fd 36>, #<IO:fd 38>, #<Thread:0x007fdd690dd7b8 sleep>]

stdout.gets
=> nil

stderr.gets
=> "date: illegal option -- -\n"

stdin.close
stdout.close
stderr.close

If you need to wait for the child process to finish before continuing, use the block format

Open3.popen3('slow --cmd') do |stdin, stdout, stderr|
  stdout.gets
end

Read more about Open3 on RubyDoc: http://www.ruby-doc.org/stdlib-2.0/libdoc/open3/rdoc/Open3.html

This article is also really great: http://tech.natemurray.com/2007/03/ruby-shell-commands.html