my $ret=`sh -e '$cmd' 2>&1`;
Didn't you mean -c ?
for my $cmd ('date', 'dat', 'date -foo') {
print "cmd: $cmd\n";
my $out = `sh -c '$cmd' 2>&1`;
my $rc = $? >> 8;
print "out: $out";
print "rc: $rc\n\n";
}
__END__
cmd: date
out: Wed Jan 4 22:40:20 CET 2012
rc: 0
cmd: dat
out: sh: dat: not found
rc: 127
cmd: date -foo
out: date: `oo': No such file or directory
rc: 1
| [reply] [Watch: Dir/Any] [d/l] [select] |
Could you pls explain why I need open one more shell?
Do I need to do the same when calling external scripts(perl,python) ?
| [reply] [Watch: Dir/Any] |
There is no extra shell being called. While it's normally the shell that does the 2>&1 redirection, Perl is doing some optimisations to not call the shell when it can be avoided. For example, in the above case, when you say my $out = `date 2>&1`, Perl does the redirection itself, and execs date directly. When you, however, specify an executable which isn't found, nothing is being executed at all — which is why you don't get the shell's error message in this case.
In case you want to see the shell's error message no matter what, you have to either call it explicitly (as done above), or put something in the command line that keeps Perl from making the optimisation, e.g. a semicolon (shell meta-character). In other words, the following two snippets would have the same net effect
my $out = `sh -c dat 2>&1`;
my $out = `dat ; 2>&1`; # prevent optimisation
i.e. in both cases you'd capture the error message of the shell. While in this case
my $out = `dat 2>&1`;
nothing would be executed at all, and consequently, nothing captured either. | [reply] [Watch: Dir/Any] [d/l] [select] |