2017-02-23 62 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

相關問題