open3 and background processes

D

Daniel Berger

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
 
G

Gennady Bystritsky

IO.readlines will try to read out everything until EOF, hence it "hangs" fo=
r long running background processes. Can you use IO.readline instead and mo=
dify your spawned program to output a one line message to indicate success?=
Then it will catch both errors and successful runs.

Gennady.
 
D

Daniel Berger

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 succes=
s? Then it will catch both errors and successful runs.

Ah, ok. This seems to work fine:

program =3D File.join(Dir.pwd, "miniserver.rb")

cmd =3D "ruby #{program} &"

Open3.popen3(cmd) do |stdin, stdout, stderr|
# Use readline, since readlines waits until EOF
error =3D stderr.readline

if error
error =3D [error] << stderr.readlines # Get the rest
end

puts error if error
end

puts "Done"

Many thanks,

Dan
 
G

Gennady Bystritsky

-----Original Message-----
From: Daniel Berger [mailto:[email protected]]
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 =3D File.join(Dir.pwd, "miniserver.rb")

cmd =3D "ruby #{program} &"

Open3.popen3(cmd) do |stdin, stdout, stderr|
# Use readline, since readlines waits until EOF
error =3D 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 ou=
tput something like "SUCCESS" to stderr so that you can test for this in po=
pen3 block:

error =3D stderr.readline
unless error.chomp =3D=3D "SUCCESS
# process errors here
...
end
if error
error =3D [error] << stderr.readlines # Get the rest
end

puts error if error
end

puts "Done"

Many thanks,

Dan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top