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.
···
-----Original Message-----
From: Daniel Berger [mailto:djberg96@gmail.com]
Sent: Tuesday, August 26, 2008 12:28 PM
To: ruby-talk ML
Subject: open3 and background processes
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
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
···
On Aug 26, 1:37 pm, Gennady Bystritsky <Gennady.Bystrit...@quest.com> 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.
From: Daniel Berger [mailto:djberg96@gmail.com]
Sent: Tuesday, August 26, 2008 1:09 PM
To: ruby-talk ML
Subject: Re: open3 and background processes
> 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
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
···
-----Original Message-----
On Aug 26, 1:37 pm, Gennady Bystritsky <Gennady.Bystrit...@quest.com> > wrote:
if error
error = [error] << stderr.readlines # Get the rest
end
puts error if error
end
puts "Done"
Many thanks,
Dan