【问题标题】:Perl: let open3 inherit STDIN, STDOUT, STDERRPerl:让open3继承STDIN、STDOUT、STDERR
【发布时间】:2017-07-14 16:02:16
【问题描述】:

这个打印 1..10 两次:

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

【问题讨论】:

    标签: perl popen3


    【解决方案1】:

    首先,继承句柄的正确表示法是:

    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,但不会关闭 STDIN 本身。通过此更改,您将在幸运时将列表打印两次。

    【讨论】:

    • 愚弄是好的,但我仍然无法让它读取文件两次。
    • 就像我已经解释的那样,您尝试做的事情取决于时间,这意味着只有在时间恰到好处的情况下才会发生。您的原始程序也是如此。你真的不应该做你想做的事!为了避免随机性,我在测试时将fork(); 替换为my $pid = fork(); waitpid($pid, 0) if $fork;。这确保了一个进程(父进程)仅在另一个进程(子进程)完成阅读后才调用seek,从而确保了双重打印。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-08
    • 2017-08-18
    • 2012-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-19
    相关资源
    最近更新 更多