I want to capture exit code of an external command while replacing its standard error output with a custom error message.
my $ret = system("which mysql");
if ($ret != 0) {
say "Error";
}
If mysql executable is not there, it shows which command error message, which I don’t want. How to get rid of it?
See http://perldoc.perl.org/perlfaq8.html#How-can-I-capture-STDERR-from-an-external-command%3f
How can I capture STDERR from an external command?
There are three basic ways of running external commands:
With system(), both STDOUT and STDERR will go the same place as the script’s STDOUT and STDERR, unless the system() command redirects them. Backticks and open() read only the STDOUT of your command.
You can also use the open3() function from IPC::Open3 . Benjamin Goldberg provides some sample code:
To capture a program’s STDOUT, but discard its STDERR:
To capture a program’s STDERR, but discard its STDOUT:
To capture a program’s STDERR, and let its STDOUT go to our own STDERR:
To read both a command’s STDOUT and its STDERR separately, you can redirect them to temp files, let the command run, then read the temp files:
But there’s no real need for both to be tempfiles… the following should work just as well, without deadlocking:
And it’ll be faster, too, since we can begin processing the program’s stdout immediately, rather than waiting for the program to finish.
With any of these, you can change file descriptors before the call:
or you can use Bourne shell file-descriptor redirection:
You can also use file-descriptor redirection to make STDERR a duplicate of STDOUT:
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:
This fails because the open() makes STDERR go to where STDOUT was going at the time of the open(). The backticks then make STDOUT go to a string, but don’t change STDERR (which still goes to the old STDOUT).
Note that you must use Bourne shell (sh(1) ) redirection syntax in backticks, not csh(1) ! Details on why Perl’s system() and backtick and pipe opens all use the Bourne shell are in the versus/csh.whynot article in the "Far More Than You Ever Wanted To Know" collection in http://www.cpan.org/misc/olddoc/FMTEYEWTK.tgz . To capture a command’s STDERR and STDOUT together:
To capture a command’s STDOUT but discard its STDERR:
To capture a command’s STDERR but discard its STDOUT:
To exchange a command’s STDOUT and STDERR in order to capture the STDERR but leave its STDOUT to come out our old STDERR:
To read both a command’s STDOUT and its STDERR separately, it’s easiest to redirect them separately to files, and then read from those files when the program is done:
Ordering is important in all these examples. That’s because the shell processes file descriptor redirections in strictly left to right order.
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.