Forum: Ruby Block method to yield stdout?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
List R. (Guest)
on 2008-10-20 22:21
(Received via mailing list)
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?
Mark T. (Guest)
on 2008-10-21 01:15
(Received via mailing list)
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.
List R. (Guest)
on 2008-10-21 06:44
(Received via mailing list)
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
:-(

Thanks again
Ken B. (Guest)
on 2008-10-23 04:41
(Received via mailing list)
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
This topic is locked and can not be replied to.