IO.popen on Windows to filter stdout

H

Harold Hausman

Hello all,

I've been googling and playing with this for a while, but I'm stuck
and I figured I'd ask in case anyone's done this before.

I'd like to use IO.popen, or something similar, to 'filter' the spew
coming from another programs stdout. I think I understand that I can
capture the stdout stream returned by IO.popen by using .readlines,
etc... But it still seems that the sub process is writing the output
directly to $stdout...

Of course, this is on windows, so I don't have proper fork, etc...

Is there a way to somehow "swallow" the stdout from the sub process so
it doesn't make it directly to the ruby process' stdout?

Thanks in advance for any insight,
-Harold
 
A

ara.t.howard

Hello all,

I've been googling and playing with this for a while, but I'm stuck and I
figured I'd ask in case anyone's done this before.

I'd like to use IO.popen, or something similar, to 'filter' the spew coming
from another programs stdout. I think I understand that I can capture the
stdout stream returned by IO.popen by using .readlines, etc... But it still
seems that the sub process is writing the output directly to $stdout...

Of course, this is on windows, so I don't have proper fork, etc...

Is there a way to somehow "swallow" the stdout from the sub process so it
doesn't make it directly to the ruby process' stdout?

Thanks in advance for any insight,
-Harold

probably the other process is writing to stderr. try

IO.popen( 'cmd 2>&1' ) do |pipe|
pipe.each do |line|
p line
end
end

alternatively, you may want to use systemu

http://codeforpeople.com/lib/ruby/systemu

it's __very__ easy to block a process using IO.popen on windows.

regards.

-a
 
H

Harold Hausman

probably the other process is writing to stderr. try

IO.popen( 'cmd 2>&1' ) do |pipe|
pipe.each do |line|
p line
end
end

Hi Ara, thanks for taking the time to try and help me. What you're
saying about stderr here sounds right to me, but I tried what you have
above, and I'm still seeing the output I'm trying to 'squash' (read:
block) ... Here is my code:
#########################
puts "ruby-link in the house!"
the_cmd = "old-Link.exe "
ARGV.each do |arg|
the_cmd << "\"#{arg}\" "
end

the_cmd << "2>&1"

puts "Calling: #{the_cmd}"

IO.popen( the_cmd )
#########################

And here is the output that I see: (apologies for badly wrapped lines)
ruby-link in the house!
Calling: old-Link.exe "@C:\long\path\to\some.rsp" "/NOLOGO"
"/ERRORREPORT:pROMPT" 2>&1
OLD-LINK :
<snip about 200k of nasty output from old-Link.exe>

------
So yeah, the output from old-Link.exe is still being filtered up to
the top and seen. What I'm looking for is a way to shut it up... ;)
alternatively, you may want to use systemu

http://codeforpeople.com/lib/ruby/systemu

I looked at systemu and it's not clear how it would help with this
problem. :| Apologies if I'm being dense.
it's __very__ easy to block a process using IO.popen on windows.

I thought so too. ;)

Thanks again for your time,
-Harold
 
A

ara.t.howard

Hi Ara, thanks for taking the time to try and help me. What you're
saying about stderr here sounds right to me, but I tried what you have
above, and I'm still seeing the output I'm trying to 'squash' (read:
block) ... Here is my code:
#########################
puts "ruby-link in the house!"
the_cmd = "old-Link.exe "
ARGV.each do |arg|
the_cmd << "\"#{arg}\" "
end

the_cmd << "2>&1"

puts "Calling: #{the_cmd}"

IO.popen( the_cmd )
#########################

And here is the output that I see: (apologies for badly wrapped lines)
ruby-link in the house!
Calling: old-Link.exe "@C:\long\path\to\some.rsp" "/NOLOGO"
"/ERRORREPORT:pROMPT" 2>&1
OLD-LINK :
<snip about 200k of nasty output from old-Link.exe>

hrrrm. this is a windozing type thing, but is it perhaps manipulating the
console directly? for instance, in unix, this can happen.

it's hard to say without seeing your code, and the old code, but you could try
this to prove to yourself that stdout and stderr can be diverted:

require 'tempfile'

tmp = Tempfile.new Process.pid
puts tmp.path

cmd = "put the exact command here"

STDOUT.reopen tmp.path
STDERR.reopen tmp.path

exec cmd

this should dump everything into a tempfile. if it does, then you should be
able to manipulate the code with popen fine.

------
So yeah, the output from old-Link.exe is still being filtered up to
the top and seen. What I'm looking for is a way to shut it up... ;)

I looked at systemu and it's not clear how it would help with this
problem. :| Apologies if I'm being dense.

harp:~ > cat a.rb
require 'systemu'

class Filter
def initialize prefix, io
@prefix = prefix
@io = io
end
def << line
@io << "#{ @prefix }: #{ line }"
end
end

o = Filter.new 'stdout', STDOUT
e = Filter.new 'stderr', STDERR

systemu 'ruby -e"STDOUT.puts 42; STDERR.puts 42"', :stdout => o, :stderr => e


harp:~ > ruby a.rb
stdout: 42
stderr: 42



-a
 
H

Harold Hausman

hrrrm. this is a windozing type thing, but is it perhaps manipulating the
console directly? for instance, in unix, this can happen.

I believe that the underlying executable that I'm dealing with, namely
VC8's "link.exe" is doing something very dastardly.
it's hard to say without seeing your code, and the old code, but you could try
this to prove to yourself that stdout and stderr can be diverted:

require 'tempfile'

tmp = Tempfile.new Process.pid
puts tmp.path

cmd = "put the exact command here"

STDOUT.reopen tmp.path
STDERR.reopen tmp.path

exec cmd

When I integrate the above code, a tempfile is indeed created, but it
remains empty. And what's more? I *still* see the output in the
console! :)

However, the following irb session indeed proves that stdout can be
redirected. (as well as makes me laugh out loud)

irb(main):001:0> require 'tempfile'
=> true
irb(main):002:0> tmp = Tempfile.new Process.pid
=> #<File:C:/DOCUME~1/Harold/LOCALS~1/Temp/484.484.0>
irb(main):003:0> STDOUT.reopen tmp.path

...
#hrhrhr.
harp:~ > cat a.rb
require 'systemu'

class Filter
def initialize prefix, io
@prefix = prefix
@io = io
end
def << line
@io << "#{ @prefix }: #{ line }"
end
end

o = Filter.new 'stdout', STDOUT
e = Filter.new 'stderr', STDERR

systemu 'ruby -e"STDOUT.puts 42; STDERR.puts 42"', :stdout => o, :stderr => e


harp:~ > ruby a.rb
stdout: 42
stderr: 42

This code is also awesome, but when I integrate it into my tool, it
has literally no effect on the outcome.

All of this is leading me to believe that VC8's link.exe (or as I've
renamed it 'old-Link.exe') is doing something very tricky, not
involving stdout or stderr at all.

Moreover, I've exceeded the point where solving this problem will save
me time versus watching 200k of spewed linker warnings with each build
of my software. (of course due to a 3rd party library that wont give
me their .pdb files, and a bug in VC8 which causes /IGNORE: to be
*itself* ignored on the command line of the linker.)

Oh well, thanks again for the lessons, I know more about spawning
processes from Ruby on Windows than I ever thought I would.

Regards,
-Harold
 
B

Bill Kelly

From: "Harold Hausman said:
All of this is leading me to believe that VC8's link.exe (or as I've
renamed it 'old-Link.exe') is doing something very tricky, not
involving stdout or stderr at all.

Sorry if you've already covered this (I haven't read the whole thread.)

But, have you tried redirecting link.exe's output from a DOS prompt
yet?

link blah > foo.out 2>&1

(Yes, surprisingly, cmd.exe supports 2>&1 syntax.)


Just wondered if even DOS is able to capture the output, or not?



Regards,

Bill
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,262
Messages
2,571,043
Members
48,769
Latest member
Clifft

Latest Threads

Top