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

I have a parent program, parent.pl that calls a child program, child.pl, like this:
@z=`perl child.pl -option1 -option2`
The whole command line for child.pl is in a scalar variable but that shouldn't matter. So I noticed that @z in parent.pl would return completely blank after I made some changes to child.pl. Lo and behold I had compile or syntax errors in child.pl, so none of my other error messages (written to STDOUT with "print") would be written from child.pl.

So when I'm running parent.pl, how do I capture compile errors when calling child.pl? Do I have to do something like

@z=`perl -c child.pl`;
before I do anything else? Will @z return STDERR messages or just STDOUT? If I did
@z=`perl child.pl -option1 -option2` or die "Possible compile errors in child.pl";
Would that do what I want?

Thank you. Looking for some input so I can learn more about this.

  • Comment on How to capture compile errors from child program?

Replies are listed 'Best First'.
Re: How to capture compile errors from child program?
by BrowserUk (Patriarch) on Jul 31, 2015 at 10:14 UTC
Re: How to capture compile errors from child program?
by kennethk (Abbot) on Jul 31, 2015 at 17:41 UTC
    The easy way to do external calls is using backticks. You could easily add the STDERR redirect (2>&1) to your command if you need to capture STDERR; otherwise it just interleaves the child's STDERR with the parent program's STDERR. As soon as you actually want to keep the various streams separate, I usually jump to IPC::Open3 or a full blown pipe/fork/exec as described in perlipc. There are popular wrappers out there that are supposed to handle this, e.g. Capture::Tiny, but I haven't gotten much utility from them.

    #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

      backticks may be easy and perform the same as 'open' on Windows, but backticks perform worse on *nix for some reason. The following code:
      use strict; use warnings; use Time::HiRes qw(time); use POSIX qw(strftime); timestamp(); my $fred = `echo plenty of fish`; timestamp(); warn $fred; timestamp(); open my $fh, 'echo ' . $fred . ' |'; $fred = <$fh>; close $fh; timestamp(); warn $fred; timestamp(); sub timestamp { my $t = time; my $date = strftime "%Y%m%d %H:%M:%S", localtime $t; $date .= sprintf ".%03d", ($t-int($t))*1000; print $date, "\n"; }
      produced the following results on three platforms:

      Windows: backtick: 12ms open: 11ms

      SunOS: backtick: 17ms open: 8ms

      Debian: backtick: 1ms open: 0ms

      It doesn't look too significant with the trivial subprocess above, but if the subprocess is heavier the difference increases disproportionately on Debian - enough to change site standards.

      One world, one people

        First, it's not the weight of the subprocess, it's the number of invocations that would be problematic. Second, since you are only running your code once, there are all sorts of problems with your benchmark. Use Benchmark to actually test performance.
        #!/usr/bin/perl use strict; use warnings; use Benchmark qw(:all :hireswallclock) ; cmpthese(20, { 'Backtick' => sub{`echo plenty of fish` for 1 .. 10}, 'Open' => sub{for (1 .. 10){open my $fh, "echo plenty of fish |"; +<$fh>}}, });
        outputs
        Rate Open Backtick Open 9.29/s -- -1% Backtick 9.35/s 1% --
        on my Windows box and
        Rate Open Backtick Open 85.8/s -- -10% Backtick 95.7/s 11% --
        on a Linux server (with iteration count upped to be meaningful).

        As an aside, if you are optimizing away milliseconds of overall run time, you probably shouldn't be using Perl.


        #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

Re: How to capture compile errors from child program?
by SimonPratt (Friar) on Jul 31, 2015 at 16:16 UTC

    If you don't care about capturing the text of the error, then you could do something like this:

    @z=`perl child.pl -option1 -option2`; if ($?) { ... }
    where ... is replaced by whatever you want to do to handle the error.

Re: How to capture compile errors from child program?
by Anonymous Monk on Jul 31, 2015 at 10:30 UTC
    Why do you have compile errors? Isn't that "a bug?"
      It was an "unintended feature". :)