perl – 为什么IPC :: Open3陷入僵局?
我浏览了
open3的文档,这里是我无法理解的部分:
所以我试过open3希望知道更好.这是第一次尝试: sub hung_execute { my($cmd) = @_; print "[COMMAND]: $cmdn"; my $pid = open3(my $in,my $out,my $err = gensym(),$cmd); print "[PID]: $pidn"; waitpid($pid,0); if(<$err>) { print "[ERROR] : $_" while(<$err>); die; } print "[OUTPUT]: $_" while (<$out>); } 有趣的是,我必须在这里初始化$err. 无论如何,这只是挂起,当我执行(“sort $some_file”);因为$some_file是包含4096个字符(我的机器的限制)的文本文件. 然后我查看了this FAQ,下面是我的新版本的执行: sub good_execute { my($cmd) = @_; print "[COMMAND]: $cmdn"; my $in = gensym(); #--------------------------------------------------- # using $in,$out doesn't work. it expects a glob? local *OUT = IO::File->new_tmpfile; local *ERR = IO::File->new_tmpfile; my $pid = open3($in,">&OUT",">&ERR",0); seek $_,0 for *OUT,*ERR; if(<ERR>) { print "[ERROR] : $_" while(<ERR>); die; } print "[OUTPUT]: $_" while (<OUT>); } 排序命令现在执行正常,但是我不知道为什么. [更新]阅读@ tchrist的答案后,我读了IO :: Select,经过一些更多的搜索,已经提出了这个版本的执行: sub good_execute { my($cmd) = @_; print "[COMMAND]: $cmdn"; my $pid = open3(my $in,$cmd); print "[PID]: $pidn"; my $sel = new IO::Select; $sel->add($out,$err); while(my @fhs = $sel->can_read) { foreach my $fh (@fhs) { my $line = <$fh>; unless(defined $line) { $sel->remove($fh); next; } if($fh == $out) { print "[OUTPUT]: $line"; }elsif($fh == $err) { print "[ERROR] : $line"; }else{ die "[ERROR]: This should never execute!"; } } } waitpid($pid,0); } 这是正常的,现在有一些事情变得更加清晰.但整体情况还是有点朦胧. 所以我的问题是: > hung_execute有什么问题? 解决方法
你在文档中遇到了我写的很多问题,然后是一些.你是死锁的,因为你正在等待孩子退出,然后再读取它.如果它具有超过输出的管道缓冲区,它将阻塞并再次退出.此外,您还没有关闭手柄的两端.
你也有其他错误.你不能以这种方式测试句柄上的输出,因为你刚刚做了一个阻塞的readline并抛弃了它的结果.此外,如果您尝试在stdout之前读取所有stderr,并且如果在stdout上存在多个输出管道缓冲区,那么您的孩子会阻止写入stdout,同时阻止其从stderr读取. 你真的必须使用select,或者IO :: Select来做到这一点.只有当该句柄上有输出可用时,才能从句柄中读取,除非您非常幸运,否则您不得将缓冲的调用与select混合使用. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |