sirohia has asked for the wisdom of the Perl Monks concerning the following question:

Hello, I made a simple subroutine to extract: 1/ return code, 2/ output, and 3/ error after executing a command. This works as a simple perl script, but my subroutine fails. Help please. Oh, I should explain what doesn't work. A) The command executes, but the exit code is always 0. B) Error is always empty. C) Output gets the error as well.

My sub-routine as below:
package ABCUtilities; #!/usr/bin/perl use warnings; use strict; use IPC::Open3; sub execute { my $cmd = shift; my $pid = open3(\*WRITER, \*READER, \*ERROR, $cmd); my ($err_msg, $out_msg) = ('', ''); while( my $output = <READER> ) { $out_msg .= $output; # . " <br>"; } while( my $errout = <ERROR> ) { $err_msg .= $errout; # . "<br>"; } waitpid( $pid, 0 ) or die "$!\n"; my $exit_code = $? >> 8; return ($exit_code, $err_msg, $out_msg); } 1;

Replies are listed 'Best First'.
Re: Open3 doesn't work in a sub-routine
by daxim (Curate) on Jul 05, 2012 at 07:55 UTC
    use strictures; use IPC::Open3 qw(open3); use autodie qw(:all); sub execute { my $cmd = shift; my $pid = open3(my($w, $r, $e), $cmd); my @out = defined $r ? <$r> : (); my @err = defined $e ? <$e> : (); waitpid($pid, 0); my $exit_code = $? >> 8; return $exit_code, \@out, \@err; } my ($exit_code, $out, $err) = execute 'some_command';
Re: Open3 doesn't work in a sub-routine
by ig (Vicar) on Jul 05, 2012 at 09:49 UTC

    It may not be an issue for the cases you are dealing with, but what if the command you run produces enough output to STDERR to fill the pipe before it closes STDOUT, and blocks writing STDERR. Then you will be stuck in the loop on STDOUT, waiting for that to finish, never reading STDERR, and the command will never finish because it is waiting to write to STDERR - deadlock.

    You might have a look at select.

      Or if you're just interested in capturing the stuff, IPC::Run3
Re: Open3 doesn't work in a sub-routine
by Anonymous Monk on Jul 05, 2012 at 07:41 UTC

    well, that program is incomplete, it doesn't run any code, maybe you'd like to call execute ?

      yes, I am calling execute from elsewhere.

        yes, I am calling execute from elsewhere.

        Well, that is kinda the important missing piece you need to show