Does any of this (truncated) look helpful? relevant?
C:\>perldoc -q stderr
Found in C:\Perl\lib\pods\perlfaq8.pod
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 STDOUT and STDERR, unless the "system()" command redirect
+s
them. Backticks and "open()" read only the STDOUT of your command.
You can also use the "open3()" function from "IPC::Open3". Benjami
+n
Goldberg provides some sample code:
To capture a program's STDOUT, but discard its STDERR:
use IPC::Open3;
use File::Spec;
use Symbol qw(gensym);
open(NULL, ">", File::Spec->devnull);
my $pid = open3(gensym, \*PH, ">&NULL", "cmd");
while( <PH> ) { }
waitpid($pid, 0);
To capture a program's STDERR, but discard its STDOUT:
use IPC::Open3;
use File::Spec;
use Symbol qw(gensym);
open(NULL, ">", File::Spec->devnull);
my $pid = open3(gensym, ">&NULL", \*PH, "cmd");
while( <PH> ) { }
| [reply] [Watch: Dir/Any] [d/l] |
You could go for IPC::Open3, but I've had mixed results with it (because I'm too clever for my own good). I usually do a full blown pipe, fork and exec -- maybe something like:
pipe my $cin, my $pin;
pipe my $pout, my $cout;
pipe my $perr, my $cerr;
$pin->autoflush(1);
$cout->autoflush(1);
$cerr->autoflush(1);
my $pid = fork();
warn("Fork failed\n"),return unless defined $pid;
if ($pid == 0) {
# Child fork/TDE execute
close $pin;
open STDIN, "<&", $cin or die "Map fail (STDIN): $!, $?\n";
exit 1 if fileno(STDIN) != 0;
close $pout;
close STDOUT;
open STDOUT, ">&", $cout or die "Map fail (STDOUT): $!, $?\n";
exit 1 if fileno(STDOUT) != 1;
close $perr;
close STDERR;
open STDERR, ">&", $cerr or print("Map fail (STDERR): $!, $?\n
+"),exit 1;
exit 1 if fileno(STDERR) != 2;
exec $command;
}
# Parent fork/tester
return 0 if eval {
alarm $timeout;
local $SIG{ALRM} = sub {
kill 9, $pid;
die "Calculation call failed to return with $timeout secon
+ds\n";
};
close $cin;
close $cout;
close $cerr;
close $pin;
local $/; # Slurp
my $content = eof $pout ? '' : <$pout>;
my $error = eof $perr ? '' : <$perr>;
alarm 0;
unless ($content =~ /\S/) {
if ($error =~ /\S/) {
$error =~ s/^/\t/mg;
$error =~ s/\s*$/\n/;
die "No result returned; STDERR=\n$error";
} else {
die "Case Aborted: No result, no error\n";
}
} elsif ($error =~ /\S/) {
$error =~ s/^/\t/mg;
warn "$executable output to STDERR for $case$command\n$err
+or";
}
}
where obviously, you'll nee to rework the error handling a little. This will give you complete control over all 3 pipes.
#11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.
| [reply] [Watch: Dir/Any] [d/l] |
| [reply] [Watch: Dir/Any] [d/l] [select] |
Hi,
Could you not just use 2> in the system arglist to redirect the stderr to a file? Or am I, as usual, missing something?
J.C.
| [reply] [Watch: Dir/Any] |