Perl 为分叉进程重新分配标准输出
我试图将分叉进程的Perl 为分叉进程重新分配标准输出,perl,Perl,我试图将分叉进程的STDOUT分配给管道。比如说 use warnings; use strict; use feature qw(say); use IO::Select; my $cmd='sleep 2; echo Hello'; pipe(PREAD, PWRITE); my $pid=fork(); if ($pid==0) { *STDOUT=*PWRITE; exec $cmd; die "Could not run command \"$cmd\""; } my
STDOUT
分配给管道。比如说
use warnings;
use strict;
use feature qw(say);
use IO::Select;
my $cmd='sleep 2; echo Hello';
pipe(PREAD, PWRITE);
my $pid=fork();
if ($pid==0) {
*STDOUT=*PWRITE;
exec $cmd;
die "Could not run command \"$cmd\"";
}
my $sel = IO::Select->new( \*PREAD );
say "Waiting for background process..";
while (1) {
my @ready = $sel->can_read;
last if (! @ready);
for my $fh (@ready) {
say "Processing file descriptor ".($fh->fileno());
my $line=<$fh>;
if (! defined $line) {
say "EOF";
$sel->remove($fh);
next;
}
chomp($line);
say "Got line: \"$line\"..";
}
}
waitpid ($pid,0);
say "Done.";
使用警告;
严格使用;
使用特征qw(例如);
使用IO::Select;
我的$cmd='sleep 2;回音“你好”;
管道(预涂、预涂);
我的$pid=fork();
如果($pid==0){
*STDOUT=*PWRITE;
exec$cmd;
die“无法运行命令\“$cmd\”;
}
我的$sel=IO::选择->新建(\*PREAD);
说“等待后台进程…”;
而(1){
我的@ready=$sel->can\u read;
最后一个if(!@ready);
我的$fh(@ready){
说“正在处理文件描述符”。($fh->fileno());
我的$line=;
如果(!定义的$line){
说“EOF”;
$sel->remove($fh);
下一个
}
chomp($line);
说“Got line:\“$line\”;
}
}
waitpid($pid,0);
说“完成”;
但管道中没有显示任何内容PREAD
;子对象仍然输出到标准输出,而不是管道
*STDOUT=*PWRITE
这只会将perl文件句柄PWRITE分配给perl文件句柄STDOUT,而不会更改操作系统的底层文件描述符。为此,您需要将基础文件描述符从PWRITE复制到fd1(STDOUT):
打开(标准输出,“>”和“写入”)
完成后,此PWRITE将被复制,现在可以作为PWRITE和STDOUT访问。一种好的方式是
关闭(PWRITE)
,然后使STDOUT成为写入管道的唯一文件句柄。@hobbs:你说得对,我相应地修改了它。谢谢Steffen,这很有效。。但是现在,select
循环没有结束。。如何在select
循环中检测EOF?在PWRITE关闭之前,PREAD不会返回EOF。在exec
完成后,它在子进程中关闭,但在父进程中仍保持打开状态。因此,您需要在fork.perl有一个快捷方式后的父级中添加一个显式的close(PWRITE)
:打开我的$pipe,'$cmd |'或打开我的$pipe,'-|',$cmd,@args
。看。