Duncan Bayne has asked for the wisdom of the Perl Monks concerning the following question:

Hi All,

I'm trying to execute a command-line program called myprogram that, upon failure, writes some text to STDERR. What I'd like to do is open a pipe to that program, and capture the output from STDERR. Something like this:

$Result = ""; open($ResultPipe, "./myprogram |"); while ( <$ResultPipe> ) { $Result = "$Result$_"; } close($ResultPipe);

Of course, this doesn't work - it captures STDOUT from myprogram instead of STDERR. I could just redirect STDERR output to a temporary file, but I'm trying to avoid temporary files and associated nastiness.

Any help would be greatly appreciated :-)

Replies are listed 'Best First'.
Re: Capturing STDERR with a pipe
by graff (Chancellor) on Aug 20, 2002 at 05:12 UTC
    You didn't actually say for certain whether "myprogram" also writes data to STDOUT as well as STDERR -- and if so, whether you want to keep both sets of data. Here are three scenarios, with suggestions for each (assuming a standard bourne-style shell is invoked by the "open" call):
    • myprogram only writes to STDERR, never to stdout:
      open( $ResultPipe, "./myprogram 2>&1 |" );
    • myprogram writes to STDERR and STDOUT, but you want to ignore whatever gets written to stdout:
      open( $ResultPipe, "./myprogram 2>&1 > /dev/null |" );
    • myprogram writes to STDERR and STDOUT, and you want to capture both... well, one of them needs to be redirected to a file, and STDERR is the normal choice for that:
      open( $ResultPipe, "./myprogram 2> /tmp/err.$$ |" );
      You really do not want to deal with them both together as a single stream (even if myprogram is designed so that all STDERR output lines match a consistent pattern), because there's a risk that a single line of STDOUT will be broken up by an intruding STDERR message.

    You would need to read the part about redirection in the "sh" or "bash" man page to understand (or at least see examples of) the ordering of the redirection operators and their various meanings.

Re: Capturing STDERR with a pipe
by kshepherd (Initiate) on Aug 20, 2002 at 05:02 UTC
    Try playing with IPC::Open3? It's basically open() with
    error handling. I'm just about to have a play myself.

    (I'm sure I don't need to paste the doc here as you're
    quite capable of driving a search engine ;))

    Small world, eh?

    -kim. (fellow nzlug'er/sunrescuer)
(jeffa) Re: Capturing STDERR with a pipe
by jeffa (Bishop) on Aug 20, 2002 at 03:24 UTC
    Redirect to /dev/null maybe?
    open($ResultPipe, "./myprogram 1>/dev/null |");
    # or maybe open($ResultPipe, "./myprogram 2&1>/dev/null |");
    UPDATE:
    oops ... looks like you want to keep STDOUT as well (thanks for the heads-up, BrowserUk). Have you tried IO::Tee? (thanks ksheperd ... IPC::Open3 is what i was trying to recommend ... jeffa shakes cob webs out of brain).

    UPDATE (round 2)

    Ok. this isn't probably the best solution, but why not just redirect STDERR to some kind of error log:
    open($ResultPipe, "./myprogram 2>>./err_log |");

    jeffa

    should have just gone to bed ... :)