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

Hello monks,

I'm currently writing a wrapper to run another program. Now i run the program N times and reformat its output into another format. However the program that I run seems to output some useless lines into STDERR and i would like to get rid of these. I run the program like this:
# @exec has the commad that i wish to run open (T_RES,"@exec |") or die "Unable to fork '@exec': $!"; while (<T_RES>) { # parsing the output }
This allows the output parsing to read the T_RES as a file, which don't require me the save all the output into memory. However this way does not capture the STDERR. Is there a way to capture the STDERR in this way as well? Is there another way which would be as easily used and require little memory?

Replies are listed 'Best First'.
Re: Redirecting and using output from executed program
by Velaki (Chaplain) on Sep 30, 2004 at 10:15 UTC

    Two ways of doing this might be the shell redirect method

    # @exec has the commad that i wish to run # but we're throwing away the error meesages open (T_RES,"@exec 2>/dev/null |") or die "Unable to fork '@exec': $!"; while (<T_RES>) { # parsing the output }
    and the Perl IPC method
    # @exec has the commad that i wish to run use IPC::Open3 my $pid; $pid = open (WTR,T_RES,ERR,"@exec") or die "Unable to fork '@exec': $!"; while (<T_RES>) { # parsing the output } waitpid $pid, 0; # if necessary, see below

    Thought the shell method might be easier, the IPC::Open3 method might be more portable.

    Note:
    With the IPC::Open3 method, you might have to waitpid to reap the process.

    Hope that helped,
    -v
    "Perl. There is no substitute."
      Or if you want to keep STDERR, 2>&1 instead of 2>/dev/null would be nice. This may be sensitive to your choice of shell.

      Also try the IO::Capture modules.

Re: Redirecting and using output from executed program
by tachyon (Chancellor) on Sep 30, 2004 at 08:03 UTC

    STDERR is file descriptor 2, STDOUT is descriptor 1. You can redirect it wherever you want:

    # no redirection C:\>perl -e "warn 'foo'" foo at -e line 1. # redirect STDERR to FILE (often /dev/null :-) C:\>perl -e "warn 'foo'" 2> out C:\>type out foo at -e line 1. # redirect STDERR to STDOUT C:\>perl -e "warn 'foo'" 2>&1 foo at -e line 1. # redirect STDERR to STDOUT and STDOUT to FILE C:\>perl -e "warn 'foo';print 'bar'">out 2>&1 C:\>type out foo at -e line 1. bar

    cheers

    tachyon

      I don't want to redirect my own scripts STDERR anywhere (unless that is the only option, then obviously I must). I want to redirect/edit the STDERR from the program I execute. Every rediction must be done within script, as the script will be called by others programs eventually.

        It is no different within yor script, just open (T_RES,"@exec 2>&1 |")

Re: Redirecting and using output from executed program
by insaniac (Friar) on Oct 01, 2004 at 11:12 UTC
    Hey,

    I don't know if this is one of the best solutions, but I did it once like this:
    open(LOG_FILE,">$log_file") || die "Unable to open $log_file: $!\n"; my $old_err = *STDERR; my $old_out = *STDOUT; # Redirecting STDERR and STDOUT to the log file handle *STDERR = \*LOG_FILE; *STDOUT = \*LOG_FILE;
    and all standard print messages go to the log file, as well as all the error messages... yes, even the error messages of executed commands ;-)
    --
    to ask a question is a moment of shame
    to remain ignorant is a lifelong shame