A piggy bank of commands, fixes, succinct reviews, some mini articles and technical opinions from a (mostly) Perl developer.

Run an external command from Perl, capturing both the output and the exit value


# This is how to run an external command from Perl,
# capturing both the output and the exit value

sub run_external_command {
    my ($self, $command) = @_;
    $self->logger->debug("Running command: $command");

    my $output = '';
    $command .= ' 2>&1 | '; # capture all output
    open(my $capture, $command);
    {
        local $/ = undef;
        $output = <$capture>;
    }
    close($capture);
    chomp($output);

    my $exit_value = ${^CHILD_ERROR_NATIVE} >> 8;
    $self->logger->debug("Exit value of command: '$exit_value'");
    $self->logger->debug("Output of command: '".($output || '[no output]')."'");

    return ($exit_value, $output);
}

This is another way:

use IPC::Open3;

sub run_external_command_2 {
  local (*my_in, *my_out, *my_err);

  my $command = "some command here that might error";
  my $pid = open3(\*my_in, \*my_out, \*my_err, $command) or die($!);

  close(my_in);
  my $std_out = do { local $/; };close(my_out);
  my $std_err = do { local $/; };close(my_err);

  waitpid($pid, 0);
  my $exit_code = $? >> 8;

  return { exit_code => $exit_code, std_out => $std_out, std_err => $std_err };
}