16.7. Reading STDERR from a ProgramProblem
You want to run a program as you would with Solution
Use the shell's numeric redirection and duplication syntax for file descriptors. (We don't check the return value from To capture a command's STDERR and STDOUT together: $output = `cmd 2>&1`; # with backticks # or $pid = open(PH, "cmd 2>&1 |"); # with an open pipe while (<PH>) { } # plus a read To capture a command's STDOUT and discard its STDERR: $output = `cmd 2>/dev/null`; # with backticks # or $pid = open(PH, "cmd 2>/dev/null |"); # with an open pipe while (<PH>) { } # plus a read To capture a command's STDERR and discard its STDOUT: $output = `cmd 2>&1 1>/dev/null`; # with backticks # or $pid = open(PH, "cmd 2>&1 1>/dev/null |"); # with an open pipe while (<PH>) { } # plus a read To exchange a command's STDOUT and STDERR, i.e., capture the STDERR but have its STDOUT come out on our old STDERR: $output = `cmd 3>&1 1>&2 2>&3 3>&-`; # with backticks # or $pid = open(PH, "cmd 3>&1 1>&2 2>&3 3>&-|"); # 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"); Discussion
When you launch a command with backticks, a piped Here is a table of interesting shell file descriptor redirections:
Using this, let's examine the most complicated of the redirection sequences from the solution section: $output = `cmd 3>&1 1>&2 2>&3 3>&-`; There are four steps here:
If that's confusing, it might help to think in terms of regular variables and a sequence of assignment statements, with $fd3 = $fd1; $fd1 = $fd2; $fd2 = $fd3; $fd3 = undef; When all's said and done, the string returned from the backticks is the command's STDERR, and its STDOUT has been diverted to the original 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. If that's confusing, think in terms of assignments to variables representing file descriptors: # system ("prog args 1>tmpfile 2>&1"); $fd1 = "tmpfile"; # change stdout destination first $fd2 = $fd1; # now point stderr there, too is very different from: # system("prog args 2>&1 1>tmpfile"); $fd2 = $fd1; # stderr same destination as stdout $fd1 = "tmpfile"; # but change stdout destination See Also
Your system's
sh
(1) manpage (if you have one) for details about file descriptor redirection; the
|
|