exit status returns '0' even with command failure

Viewed 315

I want to redirect my command output (standard output and standard error) to test.log file with below code.

I am trying to check the exit status of my command by giving some invalid option (-force) to ls

use strict;
use warnings;

#system("ls 2>&1 | tee logfile");
#system("ls > lllog ");'
my $cmd = &exec_cmd("cd reg_folder && ls -force 2>&1 | tee test.log");

sub exec_cmd{
   system(@_);
   my $result = $?;
   print "===result $result===\n";
   if(($result) != 0) {
     print "status $result\n";
     exit;
   }
   return $result;
}

Output:-

ls: invalid option -- 'e'
Try `ls --help' for more information.
===result 0===

After running system command , I am expecting the exit status should be non-zero and it has to enter if block. But it is showing exit status as 0 though the command failed.

Thanks.

1 Answers

The problem is because you're piping output into tee test.log. The exit status of a pipeline is the exit status of the last command in the pipeline, and tee is exiting successfully.

The pipefail shell option (which is available in bash but not in a legacy Bourne shell) modifies this behavior:

The return status of a pipeline is the exit status of the last command, unless the pipefail option is enabled. If pipefail is enabled, the pipeline's return status is the value of the last (rightmost) command to exit with a non-zero status, or zero if all commands exit successfully. (from the bash(1) man page)

So if you were to write...

my $cmd = &exec_cmd("set -o pipefail; cd reg_folder && ls -force 2>&1 | tee test.log");

...you'll get the exit code you expect.


Alternatively, you could handle more of the mechanics in Perl rather than relying on the shell for i/o redirection, etc.

Related