我想使用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