Questions about stdout/stderr combining (for Windows & Linux)

I’m working on a build tool, and I need to execute various
compilers/linkers and capture their output (both stdout and stderr) for
Windows and Linux compilations (msvc & gcc).
The problem is I want the output to stderr and stdout to go to the same
pipe (same result as if you were running the program from the
command-line). I can use a hack like:
out = cmd /c \"#{cmdLine}\" >bs.out 2>&1
on windows and then simply read bs.out (which will contain both stdout
and stderr), but I’d prefer to avoid the overhead (and platform specific
code) of spawning cmd.exe to run another program.
I’d prefer to use something like popen, but in a way that lets me get a
single pipe I can read from that the process’s stdout & stderr pipes are
connected to.
Due to different compiler’s general messages and warnings/errors being
logged interchangably to stdout or stderr, it’s not really feasible to
have the pipes be separate.

Any suggestions?

···


Patrick

Hello,

I am currently reading the book ‘Programming Ruby’ and during this time
I want to write same scripts with the new stuff I’ve learned. At the
moment I search a smart way to copy a file and I want to say sorry but I
didn’t find a methode like FILE#copy(theNewFileName) or
FILE.copy(theOldFileName, theNewFileName). Is there another way to do
this?

One way I find:

  • open the file which I want to copy
  • read each line and write each one into the new file at a the place I
    want to copy it…

But that is not so smart like the other stuff of ruby…

At last I want to say sorry for my bad english, it is so hard for me to
speak and write my native language and so there is no way for me to
write english a better way (-;

best regards

bovi

Patrick Bennett wrote:

I’m working on a build tool, and I need to execute various
compilers/linkers and capture their output (both stdout and stderr) for
Windows and Linux compilations (msvc & gcc).
The problem is I want the output to stderr and stdout to go to the same
pipe (same result as if you were running the program from the
command-line). I can use a hack like:
out = cmd /c \"#{cmdLine}\" >bs.out 2>&1
on windows and then simply read bs.out (which will contain both stdout
and stderr), but I’d prefer to avoid the overhead (and platform specific
code) of spawning cmd.exe to run another program.
I’d prefer to use something like popen, but in a way that lets me get a
single pipe I can read from that the process’s stdout & stderr pipes are
connected to.
Due to different compiler’s general messages and warnings/errors being
logged interchangably to stdout or stderr, it’s not really feasible to
have the pipes be separate.

What about separate pipes, two threads reading them and putting messages
in a queue, and a third thread pulling messages in from the queue?

Patrick Bennett wrote:

I’m working on a build tool, and I need to execute various
compilers/linkers and capture their output (both stdout and stderr) for
Windows and Linux compilations (msvc & gcc).
(…)
I’d prefer to use something like popen, but in a way that lets me get a
single pipe I can read from that the process’s stdout & stderr pipes are
connected to.

This works for me on Windows 2000, Ruby 1.8.0:

D:\Temp>type r.rb

def parent
IO.popen “ruby #{FILE} child 2>&1” do |io|
while line = io.gets
puts “got #{line}”
end
end
end

def child
$stdout.puts “child 1 out”; $stdout.flush
$stderr.puts “child 2 err”; $stderr.flush
$stderr.puts “child 3 err”; $stderr.flush
$stdout.puts “child 4 out”; $stdout.flush
end

ARGV.empty? ? parent : child

D:\Temp>r
got child 1 out
got child 2 err
got child 3 err
got child 4 out

D:\Temp>

HTH

Regards,
Pit

fileutils wouldnt do the trick, no ?

http://www.ruby-doc.org/stdlib/libdoc/fileutils/rdoc/index.html

Cheers

Rove

Daniel Bovensiepen wrote:

···

Hello,

I am currently reading the book ‘Programming Ruby’ and during this time
I want to write same scripts with the new stuff I’ve learned. At the
moment I search a smart way to copy a file and I want to say sorry but I
didn’t find a methode like FILE#copy(theNewFileName) or
FILE.copy(theOldFileName, theNewFileName). Is there another way to do
this?

One way I find:

  • open the file which I want to copy
  • read each line and write each one into the new file at a the place I
    want to copy it…

But that is not so smart like the other stuff of ruby…

At last I want to say sorry for my bad english, it is so hard for me to
speak and write my native language and so there is no way for me to
write english a better way (-;

best regards

bovi


Rove Monteux
Systems Administrator

rove.monteux@fluid-rock.com

Joel VanderWerf wrote:

What about separate pipes, two threads reading them and putting
messages in a queue, and a third thread pulling messages in from the
queue?

It wouldn’t work. Messages could still appear out of order unfortunately.

thanks thanks
and thanks…

···

On Mon, 2004-02-02 at 21:09, Rove Monteux wrote:

fileutils wouldnt do the trick, no ?

http://www.ruby-doc.org/stdlib/libdoc/fileutils/rdoc/index.html

Cheers

Rove

Daniel Bovensiepen wrote:

Hello,

I am currently reading the book ‘Programming Ruby’ and during this time
I want to write same scripts with the new stuff I’ve learned. At the
moment I search a smart way to copy a file and I want to say sorry but I
didn’t find a methode like FILE#copy(theNewFileName) or
FILE.copy(theOldFileName, theNewFileName). Is there another way to do
this?

One way I find:

  • open the file which I want to copy
  • read each line and write each one into the new file at a the place I
    want to copy it…

But that is not so smart like the other stuff of ruby…

At last I want to say sorry for my bad english, it is so hard for me to
speak and write my native language and so there is no way for me to
write english a better way (-;

best regards

bovi

why not use ruby to do the deed for you?

~/eg/ruby > cat a.rb
#!/usr/bin/env ruby
require ‘rbconfig’

class Spawn
class << self; alias new; end
RUBY = File.join(Config::CONFIG[“bindir”], Config::CONFIG[“ruby_install_name”])
PROGRAM = <<-code
STDERR.reopen(STDOUT)
exec(*ARGV)
code
attr :out
def initialize argv
@out = #{ RUBY } -e '#{ PROGRAM }' #{ argv.join(' ') }
end
end

stdout_stderr = Spawn[ ARGV ].out
puts “STDOUT_STDERR:\n”
puts stdout_stderr

~/eg/ruby > a.rb ls a.rb
STDOUT_STDERR:
a.rb

~/eg/ruby > a.rb ls does-not-exist
STDOUT_STDERR:
ls: does-not-exist: No such file or directory

i have not tested this on windows - but something like this should work.

-a

···

On Tue, 3 Feb 2004, Patrick Bennett wrote:

Date: Tue, 3 Feb 2004 06:03:48 +0900
From: Patrick Bennett patrick.bennett@inin.com
Newsgroups: comp.lang.ruby
Subject: Re: Questions about stdout/stderr combining (for Windows & Linux)

Joel VanderWerf wrote:

What about separate pipes, two threads reading them and putting
messages in a queue, and a third thread pulling messages in from the
queue?

It wouldn’t work. Messages could still appear out of order unfortunately.

ATTN: please update your address books with address below!

===============================================================================

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328
STP :: Solar-Terrestrial Physics Data | NCEI
NGDC :: http://www.ngdc.noaa.gov/
NESDIS :: http://www.nesdis.noaa.gov/
NOAA :: http://www.noaa.gov/
US DOC :: http://www.commerce.gov/

The difference between art and science is that science is what we
understand well enough to explain to a computer.
Art is everything else.
– Donald Knuth, “Discover”

/bin/sh -c ‘for l in ruby perl;do $l -e “print "\x3a\x2d\x29\x0a"”;done’
===============================================================================