Perl FAQ 5.15: How can I capture STDERR from an external command?

Perl FAQ 5.15

How can I capture STDERR from an external command?

There are three basic ways of running external commands:

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

In the first case, both STDOUT and STDERR will go the same place as the script's versions of these, unless redirected. You can always put them where you want them and then read them back when the system returns. In the second and third cases, you are reading the STDOUT only of your command. If you would like to have merged STDOUT and STDERR, you can use shell file-descriptor redirection to dup STDERR to STDOUT:

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

Another possibility is to run STDERR into a file and read the file later, as in

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

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
Here's a way to read from both of them and know which descriptor you got each line from. The trick is to pipe only STDOUT through sed, which then marks each of its lines, and then sends that back into a merged STDOUT/STDERR stream, from which your Perl program then reads a line at a time:

    open (CMD, 
      "(cmd args | sed 's/^/STDOUT:/') 2>&1 |");

    while () {
      if (s/^STDOUT://)  {
          print "line from stdout: ", $_;
      } else {
          print "line from stderr: ", $_;

Be apprised that you must use Bourne shell redirection syntax in backticks, not csh! For details on how lucky you are that perl's system() and backtick and pipe opens all use Bourne shell, fetch the file from called /pub/csh.whynot -- and you'll be glad that perl's shell interface is the Bourne shell.

There's an &open3 routine out there which was merged with &open2 in perl5 production.

Other resources at this site: