Block method to yield stdout?


#1

All, I’ve written a distribution service that spawns processes using
IO.popen in a seperate thread for each job.

In my Task class, I would like to create a block method such as
‘Task.monitor(mode=“stdout”)’, which would yield the stdout for that
task from that point forward. – similar to tail -f, but for a
multithreaded environment.

The result would in essence be called like:

task = Task.new(:cmd => “tail -f /some/log”)
sleep 10
task.monitor

fresh content from some/log will be yielded

Since $stdout is global, what would be the beat way tackle this?


#2

On Oct 20, 2:19 pm, “List.rb” removed_email_address@domain.invalid wrote:

In my Task class, I would like to create a block method such as
‘Task.monitor(mode=“stdout”)’, which would yield the stdout for that
task from that point forward. – similar to tail -f

Have you seen File::Tail?
http://file-tail.rubyforge.org/doc/index.html

– Mark.


#3

On Mon, 20 Oct 2008 13:19:56 -0500, List.rb wrote:

task = Task.new(:cmd => “tail -f /some/log”) sleep 10
task.monitor

fresh content from some/log will be yielded

Since $stdout is global, what would be the beat way tackle this?

Maybe use Open3, or popen. Worst case, look at how Open3 does a
fork/exec
to call the appropriate program.

–Ken


#4

On Mon, Oct 20, 2008 at 5:13 PM, Mark T. removed_email_address@domain.invalid
wrote:

Thanks Mark for replying. Yes I have used Tail before but what I’m
looking
for is more along the lines of a non-blocking version of IO#readlines

Currently, I do this on the server side:

def spawn(job)
task = Task.new(job)
queue = Queue.new
Thread.new(queue) {|q|
pipe = IO.popen(task.job.cmd)
q.push(pipe)
q.push(pipe.pid)
task.pid = pipe.pid
begin
Thread.new {
task.output = pipe.readlines
pipe.close
task.exitstatus = $?.exitstatus
task.history << {:completed => Time.now}
}
rescue => e
q.push e
end
}
queue.clear
self.tasks.push(task)
return task
end

Since IO#readlines blocks, I am not sure how to tap into the process
output
:frowning:

Thanks again