Hi all,
I’ve got a poor man’s init script where I’m firing off a Ruby process
in the background if it’s not already running.
If the process fails, no problemo. The process I called dies, I pull
the error from the stderr handle via readlines, and fire off an email
to myself. But if the process succeeds, IO#readlines hangs because
there’s no data to be read, so it just hangs there waiting for it.
One solution I came up with was to wrap the IO#readlines in a timeout,
but that feels clunky. Is there a better way to do this?
require ‘open3’
require ‘timeout’
program = File.join(Dir.pwd, “miniserver.rb”)
cmd = “ruby #{program} &”
Open3.popen3(cmd) do |stdin, stdout, stderr|
begin
# Better way?
Timeout.timeout(2){
error = stderr.readlines
}
rescue Timeout::Error
puts “Timeout”
break
end
puts error.join("\n") if error
end
puts “Done”
Where “miniserver.rb” is just a simple loop/print/sleep program. I
thought there was a way to peek ahead on an IO object to see if any
data is available on the handle before attempting to read it, but
perhaps I’m glossing over the appropriate method.
Suggestions?
Thanks,
Dan
IO.readlines will try to read out everything until EOF, hence it “hangs”
for long running background processes. Can you use IO.readline instead
and modify your spawned program to output a one line message to indicate
success? Then it will catch both errors and successful runs.
Gennady.
On Aug 26, 1:37 pm, Gennady B. [email protected]
wrote:
IO.readlines will try to read out everything until EOF, hence it “hangs” for long running background processes. Can you use IO.readline instead and modify your spawned program to output a one line message to indicate success? Then it will catch both errors and successful runs.
Ah, ok. This seems to work fine:
program = File.join(Dir.pwd, “miniserver.rb”)
cmd = “ruby #{program} &”
Open3.popen3(cmd) do |stdin, stdout, stderr|
Use readline, since readlines waits until EOF
error = stderr.readline
if error
error = [error] << stderr.readlines # Get the rest
end
puts error if error
end
puts “Done”
Many thanks,
Dan
IO.readlines will try to read out everything until EOF, hence it
Open3.popen3(cmd) do |stdin, stdout, stderr|
Use readline, since readlines waits until EOF
error = stderr.readline
The problem here is that if your miniserver.rb does not output anything
to stderr in case of no error, stderr.readline will hang as well until
it gets a newline. What I meant in my previous reply is that
miniserver.rb must output something like “SUCCESS” to stderr so that you
can test for this in popen3 block:
error = stderr.readline
unless error.chomp == "SUCCESS
# process errors here
...
end