sencer
sencer

Reputation: 377

Running an interactive program from Ruby

I am trying to run gnuplot from ruby (not using an external gem) and parsing its textual output also. I tried IO.popen, PTY.spawn and Open3.popen3 but whenever I try to get the output it just "hangs" -I guess waiting for more output to come. I feel like its somehow done using Thread.new but I couldn't find the correct way to implement it.

Anyone know how it is done?

Upvotes: 3

Views: 1871

Answers (2)

the Tin Man
the Tin Man

Reputation: 160553

The problem is that the sub-program is waiting for input that isn't being sent.

Typically, when we call a program that expects input on STDIN, we have to close STDIN, which then signals that program to begin processing. Look through the various Open3 methods and you'll see where stdin.close occurs in many examples, but they don't explain why.

Open3 also includes capture2 and capture3, which make it nice when trying to deal with a program that wants STDIN and you don't have anything to send to it. In both methods, STDIN is immediately closed, and the method returns the STDOUT, STDERR and exit status of the called program.


You need "expect" functionality. Ruby's Pty class includes an expect method.

Creates and managed pseudo terminals (PTYs). See also en.wikipedia.org/wiki/Pseudo_terminal

It's not very well documented though, and doesn't offer a lot of functionality from what I've seen. An example of its use is available at "Using Ruby Expect Library to Reboot Ruckus Wireless Access Points via ssh".

Instead, you might want to look at RubyExpect which is better documented and appears to be current.

Upvotes: 1

Thomas
Thomas

Reputation: 1633

I guess this is what you want:

require 'pty'
require 'expect'

PTY.spawn('gnuplot') do |input, output, pid|
  str = input.expect(/gnuplot>/)
  puts str
  output.puts "mlqksdf"

  str = input.expect(/gnuplot>/)
  puts str
  output.puts "exit"
end

Upvotes: 3

Related Questions