Arya McCarthy
Arya McCarthy

Reputation: 8829

How to read errors from a child process?

I have a Perl script to call another program. One section looks like this:

open(AMPL,"|ampl");
select(AMPL);
printf "option solver cplex;\n";
printf "var x1;\n"
printf "var x2;\n"
printf "minimize z: 3*x1 + 2*x2;\n";
printf "another_command;\n";
printf "data $ARGV[0];\n";
# More printfs
close(AMPL);

This code fails silently if instructions passed to ampl (that is, AMPL) are incorrect. Can the failures be either printed to STDERR or otherwise caught to abort the script?


EDIT: To clarify, this code pipes into an interactive session with the AMPL interpreter:

$ ampl
ampl: option solver cplex;
>>> var x1;
>>> var x2;
>>> minimize z: 3*x1 + 2*x2;
>>> another_command;
>>> data foo;

Upvotes: 2

Views: 141

Answers (1)

zdim
zdim

Reputation: 66883

Use a module, for example IPC::Run3, to get all that the calling program prints to streams.

use warnings;
use strict;

use IPC::Run3;

my @cmd = ('xargs', '0', 'cat');  # display a file which name is piped in
#my @cmd = ('wc', 'c');            # count characters in the passed string

my $cmd_stdin = shift || $0;      # file name, from cmdline or this script

run3 \@cmd, [$cmd_stdin], \my $out, \my $err;

print $out if $out;  # Whatever was written by command to STDOUT
print $err if $err;  # ... and to STDERR

If the invoked program does not write to standard streams then that's out of caller's hands.

In order to include a check of whether the command itself worked see this post.


With the question update, to feed strings to STDIN of AMPL

my @cmd = ('ampl');

my @stdin = ("arg_1\n", "arg_2\n", ..., "data $ARGV[0];\n");

run3 \@cmd, \@stdin, undef, \my $stderr;

The syntax requires that the input be an arrayref. The program's output is left to go to STDOUT by setting undef above, since if it's collected into $out variable it is not seen in real time.

Upvotes: 3

Related Questions