Michael
Michael

Reputation: 522

Getting rid of ruby stdin/stdout buffering

I'm trying to write a ruby script to filter the output of a tailed file (tail -f log.log | ./my_filter.rb). I believe I've set stdin and stdout to be read synchronously, but I still see my output coming out in delayed batches, 20 or so lines at a time, rather than in realtime.

I can reproduce the problem with code as simple as:

#!/usr/bin/ruby     
                
$stdout.sync = true 
$stdin.sync = true  
                
ARGF.each do |line| 
  puts line         
end                 

Am I missing a setting to eliminate buffering, or something along those lines?

Edit: To clarify, if I just tail -f the log then I see many lines written per second.

Upvotes: 9

Views: 7958

Answers (3)

Jellicle
Jellicle

Reputation: 30216

The title of this thread includes stdin as well as stdout, so adding to the other answers, none of which addresses stdin:

$stdin.iflush # Discard anything currently in $stdin's byte buffer

Upvotes: 1

Frizlab
Frizlab

Reputation: 909

This is an old question, but the accepted answer does not fully answer the question IMHO.

You can put $stdout.sync = true at the beginning of the program to get sync output to stdout (with a require 'io/console' if needed).

Upvotes: 4

Todd A. Jacobs
Todd A. Jacobs

Reputation: 84353

If you're dealing with files, you probably want IO#fsync, which says:

Immediately writes all buffered data in ios to disk. Note that fsync differs from using IO#sync=. The latter ensures that data is flushed from Ruby’s buffers, but does not guarantee that the underlying operating system actually writes it to disk.

If you're just dealing with standard input and output, you might also try requiring io/console to see if using IO::console#ioflush gives you the behavior you need. The documentation says:

Flushes input and output buffers in kernel. You must require ‘io/console’ to use this method.

As an example, consider:

require 'io/console'

ARGF.each do |line|
  $stdout.puts line
  $stdout.ioflush
end

Upvotes: 5

Related Questions