首页 文章

Windows / Linux子进程STDIN差异

提问于
浏览
0

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

我希望它也适用于Windows,所以我为 type CON 更改了 cat ,这是一个用于打印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 回答

  • 1

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

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

    • cat 非常不寻常 . 在任一系统上缓冲完全取决于单个应用程序,但几乎所有应用程序都以相同的方式工作,并且与 cat 的工作方式不同 . cat 竭尽全力使这个场景发挥作用 .

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

    1
    first line: 1
    <deadlock>
    

    说服那些"normal"程序行缓冲而不是块缓冲其输出的方法是创建一个伪tty . 例如,这就是Expect和 unbuffer 所做的 . 当然,这对于Windows程序根据缓冲区做出的决定是不确定的,但我从来没有听说过如何做到这一点 .

相关问题