This message is one of several periodic postings to DevShed's Perl Forum intended to make it easier for Perl programmers to find answers to common questions. The core of this message represents an excerpt from the documentation provided with every Standard Distribution of Perl.

---------------------------------------------
How can I capture STDERR from an external command?

There are three basic ways of running external commands:

system $cmd; # using system()
$output = `$cmd`; # using backticks (``)
open (PIPE, "cmd |"); # using open()

With system(), both STDOUT and STDERR will go the same place as the
script's versions of these, unless the command redirects them. Backticks
and open() read only the STDOUT of your command.

With any of these, you can change file descriptors before the call:

open(STDOUT, ">logfile");
system("ls");

or you can use Bourne shell file-descriptor redirection:

$output = `$cmd 2>some_file`;
open (PIPE, "cmd 2>some_file |");

You can also use file-descriptor redirection to make STDERR a duplicate of
STDOUT:

$output = `$cmd 2>&1`;
open (PIPE, "cmd 2>&1 |");

Note that you *cannot* simply open STDERR to be a dup of STDOUT in your
Perl program and avoid calling the shell to do the redirection. This
doesn't work:

open(STDERR, ">&STDOUT");
$alloutput = `cmd args`; # stderr still escapes

This fails because the open() makes STDERR go to where STDOUT was going at
the time of the open(). The backticks then make STDOUT go to a string, but
don't change STDERR (which still goes to the old STDOUT).

Note that you *must* use Bourne shell (sh(1)) redirection syntax in
backticks, not csh(1)! Details on why Perl's system() and backtick and
pipe opens all use the Bourne shell are in http://www.perl.com/CPAN/doc/FMTEYEW...sus/csh.whynot . To capture a
command's STDERR and STDOUT together:

$output = `cmd 2>&1`; # either with backticks
$pid = open(PH, "cmd 2>&1 |"); # or with an open pipe
while (<PH>) { } # plus a read

To capture a command's STDOUT but discard its STDERR:

$output = `cmd 2>/dev/null`; # either with backticks
$pid = open(PH, "cmd 2>/dev/null |"); # or with an open pipe
while (<PH>) { } # plus a read

To capture a command's STDERR but discard its STDOUT:

$output = `cmd 2>&1 1>/dev/null`; # either with backticks
$pid = open(PH, "cmd 2>&1 1>/dev/null |"); # or with an open pipe
while (<PH>) { } # plus a read

To exchange a command's STDOUT and STDERR in order to capture the STDERR
but leave its STDOUT to come out our old STDERR:

$output = `cmd 3>&1 1>&2 2>&3 3>&-`; # either with backticks
$pid = open(PH, "cmd 3>&1 1>&2 2>&3 3>&-|");# or with an open pipe
while (<PH>) { } # plus a read

To read both a command's STDOUT and its STDERR separately, it's easiest
and safest to redirect them separately to files, and then read from those
files when the program is done:

system("program args 1>/tmp/program.stdout 2>/tmp/program.stderr");

Ordering is important in all these examples. That's because the shell
processes file descriptor redirections in strictly left to right order.

system("prog args 1>tmpfile 2>&1");
system("prog args 2>&1 1>tmpfile");

The first command sends both standard out and standard error to the
temporary file. The second command sends only the old standard output
there, and the old standard error shows up on the old standard out.
---------------------------------------------

Documents such as this have been called "Answers to Frequently Asked Questions" or FAQ for short. They serve to reduce the volume of redundant traffic on this bulletin board by providing quality answers to questions that keep comming up. If you find errors or other problems with these postings please send corrections or comments to the posting email address.


------------------
Written by Anonym0us, inspired by the original PerlFAQ Server.