我想使用IPC :: Run通过孩子的STDIN,STDOUT和STDERR(开始,泵,完成)与孩子进行通信。它似乎工作。IPC :: Run - 检测早产儿出口和封闭管道
我想知道如何检测
- 早产儿退出(如错误造成)
- 管道由孩子
我想使用IPC :: Run通过孩子的STDIN,STDOUT和STDERR(开始,泵,完成)与孩子进行通信。它似乎工作。IPC :: Run - 检测早产儿出口和封闭管道
我想知道如何检测
的pump
抛出错误的一种die
,或者将其消息写入STDERR
“全部利用,活动后调用已完成”。请参阅ROUTINES部分和pump
本身。如果孩子退出,第二种情况可能会出现。所以包裹pump
呼叫eval
,并转换警告die
赶上这两种情况下
if ($talk_to_child)
{
eval {
local $SIG{__WARN__} = sub { die "pump WARNING: @_" };
pump $harness;
};
if ([email protected]) {
print [email protected];
$talk_to_child = 0;
};
}
# ... and eval {} for finish()
但仅有这将不会削减它:当父母试图写入到该退出它得到一个SIGPIPE
一个孩子,彻底终止了这一过程。当小孩关闭流和父母尝试写入时也是如此。所以也为它安装一个信号处理程序
$SIG{PIPE} = sub {
say "$_[0]: $!";
$talk_to_child = 0; # global
};
这样父母就能够幸存SIGPIPE
。仍然需要,因为pump
也会抛出。
这些在一起照顾我想出的所有测试,实际上就像它们站立一样。尽管如此,需要处理程序和eval
中的一些处理来区分感兴趣的案例。
如果这加起来太多,另一种方法是在每次调用之前检查。请参阅this post以进行单行检查(包裹在子目录中):(1)子女是否正在使用result
,以及(2)“是否有开放式I/O通道或活动进程”,使用pumpable
。
我认为你想要两个,并且还要扔SIGPIPE
处理程序。这应该包括它。
我不能在这里更具体,因为这个问题没有提供具体细节。
更新关闭:感谢@zdim为提醒我检查SIGPIPE
信号。这里是我的答案更新,也检查SIGPIPE
:
我做了一个简单的测试,使用start
,0 pump
和finish
。这里是主要的脚本p.pl
,我用:
use feature qw(say);
use strict;
use warnings;
use IPC::Run;
my $child_in;
my $child_out;
my $child_err;
my $child_name = shift;
my $harness = eval {
IPC::Run::start [ $child_name ], \$child_in, \$child_out, \$child_err;
};
if ([email protected]) {
chomp [email protected];
die "Caught exception: '[email protected]'";
}
for (1..2) {
$child_in = "Joe$_\n";
say "Parent sleeping for 1 second..";
sleep 1;
eval {
local $SIG{PIPE} = sub {
die "Parent received SIGPIPE. "
. "Child is either dead or has closed its input pipe\n";
};
say "Sending data to child..";
my $result = $harness->pump;
say "IPC::Run::pump() returned: ", $result ? "TRUE" : "FALSE";
};
if ([email protected]) {
chomp [email protected];
say "IPC::Run::pump() failed: '[email protected]'";
last;
}
say "\$child_in = '$child_in'";
say "\$child_out = '$child_out'";
}
say "Finishing harness..";
my $res = eval {
local $SIG{PIPE} = sub {
die "Parent received SIGPIPE. "
. "Child is either dead or has closed its input pipe\n";
};
$harness->finish;
};
if ([email protected]) {
chomp [email protected];
die "IPC::Run::finish() failed: '[email protected]'\n";
}
printf "IPC::Run::finish() returned: '%s'\n", $res ? "TRUE" : "FALSE";
chomp $child_out;
say "STDOUT from child: '$child_out'";
chomp $child_err;
say "STDERR from child: '$child_err'";
say "Child returned exit code: ", $harness->result;
say "Parent exited normally.."
我使用了三个不同的子脚本:
child.pl:
#! /usr/bin/env perl
use feature qw(say);
use strict;
use warnings;
my $reply = <STDIN>;
chomp $reply;
say "Hello $reply";
my $reply2 = <STDIN>;
chomp $reply2;
say "Got second reply: $reply2";
exit 0;
输出:
$ p.pl child.pl
Parent sleeping for 1 second..
Sending data to child..
IPC::Run::pump() returned: TRUE
$child_in = ''
$child_out = ''
Parent sleeping for 1 second..
Sending data to child..
IPC::Run::pump() returned: TRUE
$child_in = ''
$child_out = ''
Finishing harness..
IPC::Run::finish() returned: 'TRUE'
STDOUT from child: 'Hello Joe1
Got second reply: Joe2'
STDERR from child: ''
Child returned exit code:
Parent exited normally..
child2.pl:
#! /usr/bin/env perl
use feature qw(say);
use strict;
use warnings;
my $reply = <STDIN>;
chomp $reply;
say "Hello $reply";
die "Child exception\n";
输出:
$ p.pl child2.pl
Parent sleeping for 1 second..
Sending data to child..
IPC::Run::pump() returned: TRUE
$child_in = ''
$child_out = ''
Parent sleeping for 1 second..
Sending data to child..
IPC::Run::pump() failed: 'Parent received SIGPIPE. Child is either dead or has closed its input pipe'
Finishing harness..
IPC::Run::finish() failed: 'Parent received SIGPIPE. Child is either dead or has closed its input pipe'
child3.pl:
#! /usr/bin/env perl
use strict;
use warnings;
close \*STDIN;
close \*STDOUT;
close \*STDERR;
sleep 5;
exit 2;
输出:
$ p.pl child3.pl
Parent sleeping for 1 second..
Sending data to child..
IPC::Run::pump() failed: 'ack Parent received SIGPIPE. Child is either dead or has closed its input pipe'
Finishing harness..
IPC::Run::finish() failed: 'Parent received SIGPIPE. Child is either dead or has closed its input pipe'
所以对于这些工商业污水附加费ts,似乎SIGPIPE
信号可用于检查孩子是否活着或已关闭其输入管道。请注意,如果您在孩子退出后尝试致电pump()
,则以前的孩子输出将丢失,请参阅child2.pl
示例。
我感兴趣的是**长**运行的孩子与大量的“命令 - 响应”序列的情况。我想避免将命令按压到封闭STDIN的孩子身上或者从封闭STDOUT的孩子那里抽取回复。 – AnFi
'SIGPIPE'很好的捕获。我认为那就是我所缺少的:) –
@HåkonHægland正确的说,'SIGPIPE'是表演的终结者。但这仍然很复杂。在每次调用之前使用'result'和'pumpable'(加上'SIGPIPE'处理程序)组合来检查可能会更简单。 – zdim
@ AndrzejA.Filip我用直接使用'result' +'pumpable'(+'SIGPIPE'处理程序)进行检查的评论更新了答案。我还编辑了一些准确的评论。我在我的测试中证实,答案中的主要方法确实可以处理所有情况,实际上就像现在这样。让我们知道它是如何为你工作的。 @Håkon的答案也得到了更新。 – zdim