From: Brian Candler Date: 2011-05-15T00:14:50+09:00 Subject: Re: Shell pipeline in Ruby? Here is a ruby 1.9.2 version with close_on_exec=. I leave it as an exercise to refactor this to an arbitrary pipeline of N commands - it would return one input pipe, one output pipe, N pids and N error pipes. Regards, Brian. #Thread.abort_on_exception = true # for debugging ruby_to_a_rd, ruby_to_a_wr = IO.pipe ruby_to_a_wr.close_on_exec = true # no children should have this a_to_b_rd, a_to_b_wr = IO.pipe a_err_rd, a_err_wr = IO.pipe a_err_rd.close_on_exec = true # no children should have this pid1 = fork do a_to_b_rd.close STDIN.reopen(ruby_to_a_rd) STDOUT.reopen(a_to_b_wr) STDERR.reopen(a_err_wr) exec("cat; echo done cat 1>&2") STDERR.puts "Whoops! #{$!}" end # we don't want these fds, nor any of the further children ruby_to_a_rd.close a_to_b_wr.close a_err_wr.close b_to_c_rd, b_to_c_wr = IO.pipe b_err_rd, b_err_wr = IO.pipe b_err_rd.close_on_exec = true # no children should have this pid2 = fork do b_to_c_rd.close STDIN.reopen(a_to_b_rd) STDOUT.reopen(b_to_c_wr) STDERR.reopen(b_err_wr) exec("tr 'a-z' 'A-Z'; echo done tr 1>&2") STDERR.puts "Whoops! #{$!}" end # we don't want these fds, nor any of the further children a_to_b_rd.close b_to_c_wr.close b_err_wr.close c_to_ruby_rd, c_to_ruby_wr = IO.pipe c_err_rd, c_err_wr = IO.pipe c_err_rd.close_on_exec = true # no children should have this pid3 = fork do c_to_ruby_rd.close STDIN.reopen(b_to_c_rd) STDOUT.reopen(c_to_ruby_wr) STDERR.reopen(c_err_wr) exec("sed 's/O/0/g'; echo done sed 1>&2") STDERR.puts "Whoops! #{$!}" end # we don't want these fds, nor any of the further children b_to_c_rd.close c_to_ruby_wr.close c_err_wr.close Thread.new do ruby_to_a_wr.puts "Here is some data" ruby_to_a_wr.puts "And some more" ruby_to_a_wr.close end Thread.new do while line = a_err_rd.gets puts "A err: #{line}" end a_err_rd.close end Thread.new do while line = b_err_rd.gets puts "B err: #{line}" end b_err_rd.close end Thread.new do while line = c_err_rd.gets puts "C err: #{line}" end c_err_rd.close end while line = c_to_ruby_rd.gets puts line end c_to_ruby_rd.close -- Posted via http://www.ruby-forum.com/.