On Tue, 17 Feb 2004, Ferenc Engard wrote:

> Date: Tue, 17 Feb 2004 05:06:08 +0900
> From: Ferenc Engard <ferenc / engard.hu>
> Newsgroups: comp.lang.ruby
> Subject: controlling external process' stdin/stdout AND getting its
>     return value
> 
> Hi all,
> 
> I want total control over an external process, i.e. handle its
> stdin/stdout as with IO.popen (also, if it is possible, handle its
> stderr, too), and I also need to get is return value.
> 
> How can I do this?
> 
> Thanks,
> Ferenc

it's tricky to manage stdout, stderr, _and_ exit status since with popen you
lose the sense of $?.  

try my session module from the raa:

  http://raa.ruby-lang.org/list.rhtml?name=session

example:

~ > cat sess.rb

  #!/usr/bin/env ruby

  # http://raa.ruby-lang.org/list.rhtml?name=session
  require 'session'

  sh = Session::Shell.new

  # ====
  puts "EXAMPLE 0" 
  stdout, stderr = sh.execute 'ls'
  puts "stdout <#{ stdout.inspect }>"
  puts "stderr <#{ stdout.inspect }>"
  puts "status <#{ sh.status }>"
  puts

  # ====
  puts "EXAMPLE 1" 
  stdout, stderr = '', '' 
  sh.execute 'ls does-not-exist', :stdout => stdout, :stderr => stderr 
  puts "stdout <#{ stdout.inspect }>"
  puts "stderr <#{ stdout.inspect }>"
  puts "status <#{ sh.exitstatus }>"
  puts

  # ====
  puts "EXAMPLE 2" 
  dev_null = open '/dev/null', 'w'
  sh.execute 'ls', :o => STDOUT, :e => dev_null 
  puts "status <#{ sh.exit_status }>"
  puts

  # ====
  puts "EXAMPLE 4" 
  org = sh.path
  p sh.path
  sh.path = ['.'] + sh.path
  p sh.path
  sh.path = "/bin/foo:/bin/bar:#{ sh.path.join ':' }"
  p sh.path
  sh.path = org
  p sh.path
  puts

  # ====
  puts "EXAMPLE 5" 
  sh = Session::Shell.new :history => true
  sh.execute 'ls'
  sh.execute 'echo foobar'
  p sh.history[0]
  p sh.history[1]
  puts

  # ====
  puts "EXAMPLE 6" 
  cmd = 'while test 1; do echo on_out; echo on_err 1>&2; sleep 1; done'
  sh.execute(cmd) do |o, e|
    puts "processing stdout <#{ o.inspect }>..." if o
    puts "processing stderr <#{ e.inspect }>..." if e
  end
  puts


~ > ruby sess.rb 

  EXAMPLE 0
  stdout <"sess.rb\nsess.rb.out\n">
  stderr <"sess.rb\nsess.rb.out\n">
  status <0>

  EXAMPLE 1
  stdout <"">
  stderr <"">
  status <1>

  EXAMPLE 2
  sess.rb
  sess.rb.out
  status <0>

  EXAMPLE 4
  ["/data/bin", "/data/bin", "/usr/kerberos/bin", "/usr/local/bin", "/bin", "/usr/bin", "/usr/X11R6/bin", "/usr/local/java/bin", ".", "~/bin", "/sbin", "/usr/sbin", "/usr/local/sbin", "/home/ahoward/bin"]
  [".", "/data/bin", "/data/bin", "/usr/kerberos/bin", "/usr/local/bin", "/bin", "/usr/bin", "/usr/X11R6/bin", "/usr/local/java/bin", ".", "~/bin", "/sbin", "/usr/sbin", "/usr/local/sbin", "/home/ahoward/bin"]
  ["/bin/foo", "/bin/bar", ".", "/data/bin", "/data/bin", "/usr/kerberos/bin", "/usr/local/bin", "/bin", "/usr/bin", "/usr/X11R6/bin", "/usr/local/java/bin", ".", "~/bin", "/sbin", "/usr/sbin", "/usr/local/sbin", "/home/ahoward/bin"]
  ["/data/bin", "/data/bin", "/usr/kerberos/bin", "/usr/local/bin", "/bin", "/usr/bin", "/usr/X11R6/bin", "/usr/local/java/bin", ".", "~/bin", "/sbin", "/usr/sbin", "/usr/local/sbin", "/home/ahoward/bin"]

  EXAMPLE 5
  cmd: <ls>
          cmdno: <3>
          out: <"sess.rb\nsess.rb.out\n">
          err: <"">
          cid: <1729_3_142581>

  cmd: <echo foobar>
          cmdno: <4>
          out: <"foobar\n">
          err: <"">
          cid: <1729_4_69019>


  EXAMPLE 6
  processing stdout <"on_out\n">...
  processing stderr <"on_err\n">...
  processing stdout <"on_out\n">...
  processing stderr <"on_err\n">...

  (loops forever)


  contact me offline with any questions - the current docs are scant but the
  above should get you going.

-a
-- 
===============================================================================
| EMAIL   :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
| PHONE   :: 303.497.6469
| ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
| URL     :: http://www.ngdc.noaa.gov/stp/
| TRY     :: for l in ruby perl;do $l -e "print \"\x3a\x2d\x29\x0a\"";done 
===============================================================================