Well, I’m sure I have nowhere as good an idea of PTY.spawn() as
Matsumoto does, but let me try to explain what your code is doing, and
how to get your desired result.
First, you might want to consider using other methods for what you’re
doing. You probably don’t really need a pseudo terminal, which is what
PTY gives you, and you can use more well documented methods. These two
links give a good overview of some of the other ways you can start
subprocesses in ruby:
http://devver.net/blog/2009/06/a-dozen-or-so-ways-to-start-sub-processes-in-ruby-part-1/
http://devver.net/blog/2009/07/a-dozen-or-so-ways-to-start-sub-processes-in-ruby-part-2/
If you still think you really need to use a pseudo terminal, then read
on.
PTY.spawn() doesn’t block your ruby program like a call to system()
would. It simply starts the process given the command, and lets you
continue. In your first email, you mentioned that when you took out the
“sleep 10” line in your code, no exception took place at all. The reason
for this is that your script ended before the child did, since the ten
seconds of sleep were taken out. And so ruby did not have a chance to
raise an exception. Similarly, in your latest code example, “TEST END”
was never printed because the
begin block had an exception before you even reached the ‘printf “TEST
END\n”’ line. The exception occurred while
it was in “sleep 10”. I hope that’s clear, it messed me up too in the
past.
To get what you want, you might want to use the block form for
PTY.spawn() instead. I just find it cleaner, and using the limited scope
for the variables pipe_read etc makes sense. The variables are gone when
the pseudo terminal is gone.
What I’ve done is put a loop inside the PTY.spawn() block, which can be
used to handle the output from the subprocess, or feed it input. If you
don’t need to do that, you probably don’t need to use PTY anyways, but
you can be the judge of that. Now, this loop stops when the subprocess
exits, and then the rest of the ruby script continues.
It seems like you also want to run some code in parallel to the
subprocess, but not in the loop I mentioned. For this case, the code
below also has a thread. Only when the child exits does the thread stop,
and “t.join” finally allows the code to continue. Before “t.join” and
after the thread block though, you can run code in parallel to the
subprocess. And then, “Test End” is printed after the subprocess has
exited. Here’s the code:
require ‘pty’
cmd = “/home3/cman/work/product/integrator/test/syb2/OCS-15_0/bin/isql
-Uuser2 -Puser2 -Scman2”
t = Thread.new do
begin
PTY.spawn(cmd) do |pipe_read, pipe_write, pid|
loop do
# Code here can handle output given by your command, and feed it
input, etc
# But the infinite loop will be broken by the exception caused
when the child process exits, and your script continues
# Or you could just terminate this loop in advance, but
remember, you might reach the end of your ruby script
# before the child exits, in case that’s a problem.
end
end
rescue PTY::ChildExited => msg
puts “The child has exited”
rescue => msg
puts “A different exception:\n” + msg
end
end
puts “Doing stuff in parallel to the subprocess here”
t.join
puts “Test End”
I hope that was useful/clear. It was certainly too long.