tags:

views:

57

answers:

2

I have an app that runs continuously, dumping output from a server and sending strings to stdout. I want to process this output with a Ruby script. The strings are \n-terminated.

For example, I'm trying to run this on the command line:

myapp.exe | my_script.rb

...with my_script.rb defined as:

while $stdin.gets
    puts $_
end

I ultimately am going to process the strings using regexes and display some summary data, but for now I'm just trying to get the basic functionality hooked up. When I run the above, I get the following error:

my_script.rb:1:in `gets': Bad file descriptor (Errno::EBADF)
        from my_script.rb:1

I am running this on Windows Server 2003 R2 SP2 and Ruby 1.8.6.

How do I continuously process stdin in a Ruby script? (Continuously as in not processing a file, but running until I kill it.)

EDIT:

I was able to make this work, sort of. There were several problems standing in my way. For one thing, it may be that using Ruby to process the piped-in stdin from another process doesn't work on Windows 2003R2. Another direction, suggested by Adrian below, was to run my script as the parent process and use popen to connect to myapp.exe as a forked child process. Unfortunately, fork isn't implemented in Windows, so this didn't work either.

Finally I was able to download POpen4, a RubyGem that does implement popen on Windows. Using this in combination with Adrian's suggestion, I was able to write this script which does what I really want -- processes the output from myapp.exe:

file: my_script.rb

require 'rubygems'
require 'popen4'

 status =
    POpen4::popen4("myapp.exe") do |stdout, stderr, stdin, pid|
        puts pid
        while s = stdout.gets
            puts s
        end

    end

This script echoes the output from myapp.exe, which is exactly what I want.

A: 

gets doesn't always use stdin but instead tries to open a file.

See SO.

mcandre
When I replace `$stdin` with `ARGF` in my code I still get the same error. Am I doing it right?
John Dibling
+1  A: 

Try just plain gets, without the $stdin. If that doesn't work, you might have to examine the output of myapp.exe for non-printable characters with another ruby script, using IO.popen.

Adrian