1

I have a small test Ruby program called "count", which counts 1..50.

#!/usr/bin/ruby
#count
for i in 1..50 do
 STDOUT.puts i
 sleep 1
end

I want to call it from another program, and read the outputted numbers line by line, and output them from the other program, line by line.

However my construction doesn't work:

IO.popen("count","r+") {|f| puts f.readline}

What should I do to make it work? Maybe some modification in the test program "count"?

1 Answer 1

3

If you have some patience (about 50s worth), you'll see that you do get one line of output and that line will be "1\n". You have two problems:

  1. count is using buffered output. This means that nothing will show up in your stdin until count's output buffer is full; given the small number of bytes that you're printing, the buffer won't be flushed until count finishes.
  2. Your popen block is only looking for one line.

You can solve the first one by using STDOUT.sync = true to turn off the output buffering in count:

STDOUT.sync = true
for i in 1..50 do
  STDOUT.puts i
  sleep 1
end

Then in your popen, you can iterate over the lines using each:

IO.popen("count","r+") { |fp| fp.each { |line| puts line } }

Then you should one line of output showing up each second.

Sign up to request clarification or add additional context in comments.

2 Comments

And what if my test program is a normal program? For example cURL or WGET, How can I set the STDOUT.sync=true in this case? Or should I write a "wrapper" Ruby program which calls the normal program?
Have you tried with curl or wget? Programs that expect to be used in pipelines tend to be pipe-aware and do The Right Thing on their own. Otherwise, you wait until the buffer fills.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.