system($command) will print $command's STDERR to your STDERR and $command's STDOUT to
your STDOUT. Apache's error log contains the STDERR output of the scripts you run
through the webserver, so if you want system($command)'s STDERR output to show up in
the browser, just redirect STDERR to STDOUT: system($command 2>&1).
If you would like to be able to know if the system call was successful (which you can
do based on system's return code) and collect the output of an external command (which
you can do with backticks ($output = `$command`) all in one command, you can use a
subroutine similar to the one below. (Unfortunately, neither system or backticks can
do both. I assume this is what system2() does, but I haven't had a chance to look).
It redirects STDOUT and STDERR to a tempfile, system()'s the arguments, collects the
output from the tempfile, and returns the output from the command if the system() was
successful, or dies with the output as an argument if the system() was unsuccessful.
I'm not sure how robust it is, but it works on Windows and Unix. I use it all the
time. I got the idea from some Perl book.
eval { $output = system_with_out($command) };
if ($@) {
# do something with error
}
Jon
sub system_with_out {
my @args = @_;
# create dups of STDOUT and STDERR
open SAVEOUT, ">&STDOUT" or confess "Couldn't open dup of STDOUT: $!";
open SAVEERR, ">&STDERR" or confess "Couldn't open dup of STDERR: $!";
# system output and error will go to $tmpfile
my $tmpfile;
do {
$tmpfile = tmpnam();
} until sysopen(STDOUT, $tmpfile, O_WRONLY | O_EXCL | O_CREAT);
# alias STDERR to STDOUT
*STDERR = *STDOUT;
# run the command
if(system(@args) != 0) {
# don't confess until we get stdout and stderr back and cleanup
open TMP, $tmpfile;
my @return = <TMP>;
close TMP;
unlink $tmpfile;
open STDOUT, ">&SAVEOUT";
open STDERR, ">&SAVEERR";
confess "Error: @args: @return";
}
# restore STDOUT and STDERR
open STDOUT, ">&SAVEOUT" or confess "Couldn't open STDOUT as dup of SAVEOUT: $!";
open STDERR, ">&SAVEERR" or confess "Couldn't open STDERR as dup of SAVEERR: $!";
# get system output
open TMP, $tmpfile close SAVEOUT; close SAVEERR; # prevent warnings
my @return = <TMP>;
close TMP;
unlink $tmpfile or confess "Couldn't delete $tmpfile: $!";
close SAVEOUT; close SAVEERR; # prevent warnings
return wantarray ? @return : join "" => @return;
}
Hi all,
I have a situation where I need to exec a command-line based perl
program from a CGI wrapper. I want to do this safely, but I also
want to see the same output from the command line program in the
browser that I would normally.
I'm not quite sure how I should go about doing this, and have it safe
as well. I'm assuming the best option is using the list form of
system()? If so, how do I get STDERR to the browser as well?
Will 'fatalsToBrowser' accomplish this? Currently stderr seems to
end up in the apache error log.
Thanks for you input.
--
Seeya,
Paul
----
God Bless America!
...we don't need to be perfect to be the best around,
and we never stop trying to be better.
Tom Clancy, The Bear and The Dragon