Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl 为分叉进程重新分配标准输出_Perl - Fatal编程技术网

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
。看。