Windows / Linux子进程STDIN的区别

时间:2015-06-17 03:37:14

标签: linux windows perl process stdin

我在工作中构建了一个简单的文本处理脚本,供其他程序使用。当我完成后,有人记得脚本不需要阻止STDIN / STDOUT使用它来正常工作,并相应地修改了脚本。该脚本通过IPC::Open2在子进程中打开* nix的cat并将STDIN打印到它,读回来然后处理并将其打印到STDOUT。我不知道如何使脚本无阻塞,但它显然有效。

我希望它也可以在Windows上运行,所以我为cat更改了type CON,这是一个用于打印STDIN的简单Windows命令。示例脚本如下:

use strict;
use warnings;
use IO::Handle;
use IPC::Open2;

my $command = ($^O eq 'MSWin32') ? 'type CON' : 'cat';

my ( $com_reader, $com_writer ) = ( IO::Handle->new, IO::Handle->new );
open2( $com_reader, $com_writer, $command );
# input
while (<STDIN>) {
    print "first line: $_";
    print $com_writer "$_";
    my $line = <$com_reader>;
    # ...process $line...

    print "next line: $line";
}

但结果完全不同。在Windows上,主脚本和子脚本的STDIN流似乎不同,而在Linux上它们是相同的。在Windows上(我在单独的输入行上输入1和2):

>perl test.pl
>1
first line: 1
>2
next line: 2
>1
>2
first line: 2
next line: 1
>1
>2
first line: 2
next line: 1
>1
>2
first line: 2
next line: 1

在Linux上(相同输入):

>perl test.pl
>1
first line: 1
next line: 1
>2
first line: 2
next line: 2
>1
first line: 1
next line: 1
>2
first line: 2
next line: 2

为什么输出不同,如何使Windows行为与Linux行为相匹配?另外,为什么这个“在子进程中打开cat并通过它输入管道”技巧呢?

1 个答案:

答案 0 :(得分:1)

这不是Windows verus Linux的事情。你只选了两个可怕的例子。

  1. type con从控制台读取,而不是从STDIN读取。这可以使用type con <nul

  2. 看到
  3. cat极不寻常。在任一系统上缓冲完全取决于单个应用程序,但几乎所有应用程序都以相同的方式工作,并且与cat的工作方式不同。 cat不遗余力地使这个场景发挥作用。

  4. cat替换为perl -pe1以查看几乎所有其他程序的行为:

    1
    first line: 1
    <deadlock>
    

    说服那些&#34;正常&#34;行缓冲而不是块缓冲它们的输出的程序是创建一个伪tty。例如,这就是Expect和unbuffer所做的。当然,这在Windows中无法运行。我不确定哪些Windows程序根据他们的缓冲决定,但我不认为它可以很容易伪造,因为我从来没有听说过如何做到这一点。