【问题标题】:How to read errors from a child process?如何从子进程中读取错误?
【发布时间】:2017-04-09 01:45:46
【问题描述】:

我有一个 Perl 脚本来调用另一个程序。其中一个部分如下所示:

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);

如果传递给ampl(即AMPL)的指令不正确,此代码会静默失败。是否可以将失败打印到 STDERR 或以其他方式捕获以中止脚本?


编辑:澄清一下,这段代码进入了与 AMPL 解释器的交互会话:

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

【问题讨论】:

  • 放大器的“不正确”?那就是ampl的业务。您正在为外部程序提供数据。它可以为所欲为。它可能会以特定代码退出,您可以捕捉到它,但如果没有,调用代码可以做的事情并不多。您可以控制放大器源吗?
  • ampl 的退出码在出错时将非零;不过,我想如果我将内容输入ampl 的 STDIN,我可以从它的 STDERR(或 STDOUT)中读取内容。
  • How to read to and write from a pipe in Perl(他们询问了获取标准输出,但获取标准错误是相似的)。
  • 既然你提到了STDERR,我认为ampl 不会在错误时写入它,否则它会在终端上结束。那是个问题。相反,如果您想在调用程序中捕获它(而不是让它去任何它想去的地方),那么有很多关于它的帖子(从外部程序重定向 X),例如链接的 ThisSuitIsBlackNot
  • 另外,还有模块......例如见IPC::Run3(链接的帖子显示IPC::Open3

标签: perl


【解决方案1】:

使用模块,例如IPC::Run3,获取调用程序打印到流的所有内容。

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

如果调用的程序没有写入标准流,那么调用者无法控制。

要检查命令本身是否有效,请参阅this post


随着问题更新,将字符串提供给 STDINAMPL

my @cmd = ('ampl');

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

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

语法要求输入是一个数组引用。通过在上面设置undef 将程序的输出留给STDOUT,因为如果它被收集到$out 变量中,它不会实时看到。

【讨论】:

  • 这真的很有启发性。 printfs 在哪里适合这个?
  • @aryamccarthy 为您的案例添加了代码。您的printf 为程序提供信息,对吗?这是由模块完成的——它将@input 中的任何内容通过管道传输到它调用的程序中(语法是使用\@input)。它还接受程序打印的任何内容并将其放入$out(和$err,如果有的话)。
  • 我再次更新了问题以表明意图:这不是将命令行参数传递给ampl 的调用。它与 AMPL 解释器交互。
  • @aryamccarthy 感谢提醒,调整了部分语句和代码。该模块提供STDIN ...我正在检查 interactive 是否真的有效。
  • @aryamccarthy 已更正:需要undef(用于标准输出)才能在STDOUT 上查看调用程序的输出。 (我原来的\undef 将它发送到/dev/null。)
猜你喜欢
  • 2012-10-06
  • 1970-01-01
  • 2020-04-29
  • 1970-01-01
  • 2016-02-11
  • 1970-01-01
  • 1970-01-01
  • 2019-05-26
  • 2023-04-02
相关资源
最近更新 更多