2017-02-23 82 views
3

该打印1..10两次:的Perl:让open3继承STDIN,STDOUT,STDERR

seq 10 > /tmp/ten 
perl -e 'fork();seek(STDIN,0,0); print <STDIN>' </tmp/ten 

我想使用IPC :: Open3做同样的,但我不能得到那个工作:

perl -MIPC::Open3 -e 'fork();seek(STDIN,0,0); open3(0,1,2,"cat");' < /tmp/ten 
perl -MIPC::Open3 -e 'fork();seek(STDIN,0,0); open3(STDIN,STDOUT,STDERR,"cat");' < /tmp/ten 
perl -MIPC::Open3 -e 'fork();seek(STDIN,0,0); open3(*STDIN,*STDOUT,*STDERR,"cat");' < /tmp/ten 
perl -MIPC::Open3 -e 'fork();seek(STDIN,0,0); open3(\*STDIN,\*STDOUT,\*STDERR,"cat");' < /tmp/ten 

回答

5

首先,正确的符号继承手柄是:

open3("<&STDIN", ">&STDOUT", ">&STDERR", "cat") 

但打印1..10两次?你不应该依赖这种事情!只有在时机恰到好处的情况下才会发生。事实上,即使对于您的原始程序,它也很少会发生。问题源于父进程和子进程共享相同文件指针的事实。

也许,以避免人靠此极不可靠行为,open3关闭第一把手时,它才造就了DUP。这是可能如下愚弄它:

open(local *CHILD_STDIN, "<&", \*STDIN) or die $!; 
open3("<&CHILD_STDIN", ">&STDOUT", ">&STDERR", "cat") 

这样,open3将关闭DUP CHILD_STDIN,而不是标准输入本身。有了这个改变,当你运气好的时候,你会得到两次打印的清单。

+0

这个鬼混很好,但我仍然无法读取文件两次。 –

+2

就像我已经解释的那样,你要做的是与时间有关,这意味着只有在时机恰到好处时才会发生。您的原始程序也是如此。你真的不应该做你想做的事!为了避免随机性,我用'my $ pid = fork();替换了'fork();'; waitpid($ pid,0)if $ fork;'测试时。这确保了一个过程(父母)在另一个过程(孩子)完成阅读后只叫'寻求',从而确保了双重打印。 – ikegami