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

Does anybody out there know how I can redirect what a shell command writes to STDERR? I found the following code in a module I work on:

 system ("($cmd) &> $log")

and then reads from the file $log. The problem with this is, it works fine with csh, but not with sh / bash. Is there a way to read STDERR which doesn't depend on the shell?

Replies are listed 'Best First'.
Re: redirecting STDERR from shell commands
by AidanLee (Chaplain) on Sep 07, 2001 at 16:17 UTC

    I believe you can simply close and re-open STDERR like so:

    close(STDERR); open(STDERR,">mylogfile.log"); print STDERR 'this goes to my log file now';
    HTH
      I was pretty sure what AidanLee posted above would work correctly, and I would suggest redirecting STDERR as busunsl posted below -- 2>$FILE. What I did *not* know would work was the following code:

      Please forgive me, but I only had access to a Windows 2000 PC. *Smiles*

      use strict; system("del doesnotexist1"); close(STDERR); open(STDERR,">stderr.out") || die "Could not open STDERR...\n"; system("del doesnotexist2");

      This results in "Could Not Find C:\TEMP\doesnotexist1" being displayed on the screen (default for STDERR) and "Could Not Find C:\TEMP\doesnotexist2" being written to stderr.out.

      Looks like system() inherits STDERR from the Perl script.

        system() forks, so just like any other forked child process, it inherits any IO handle definitions from the parent process. just fyi.
Re: redirecting STDERR from shell commands
by busunsl (Vicar) on Sep 07, 2001 at 16:31 UTC
    You can redirect STDERR like this:
    system("$cmd 2>$err");
      Fine for sh / bash / ksh, but will this work also for csh /tcsh?

      Anyway, it seems a waste to me to write to a file and then read it rather than opening a pipe. I just stumbled across the following piece of code:

      open (CMD, "$cmd 2>&1|"); $errStr = <CMD>;

      but it looks to me like this also involves the syntax of the underlying shell, or am I wrong?

        Yes, it does. That is why Perl always uses /bin/sh for system (unless Perl can handle it itself). It never uses csh, tcsh, etc.

        Of course, if you are on a system that doesn't have /bin/sh, then this might not work. For example, Win9x's cmd doesn't know about 2>&1 (but WinNT's command.exe does). This is one big reason why building CPAN modules under Win9x often doesn't work.

                - tye (but my friends call me "Tye")
Re: redirecting STDERR from shell commands
by runrig (Abbot) on Sep 07, 2001 at 19:22 UTC