【发布时间】:2023-11-24 13:11:01
【问题描述】:
我在工作中构建了一个简单的文本处理脚本,供另一个程序使用。当我完成后,有人记得脚本不需要阻止 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 行为匹配?另外,为什么这种“在子进程中打开猫并通过它管道输入”的技巧完全有效?
【问题讨论】:
-
@Harry Johnston,与子进程的双向交互通信。
-
@harry Johnston,实际上,这将是一个更复杂的程序。
-
@Nate:顺便说一下,所写的脚本行为异常的原因是脚本和子进程正在竞争相同的输入源。
-
@Harry Johnston,他们不应该使用相同的输入源。即使你解决了这个问题,他仍然会遇到问题。
-
Nate,我最好的猜测是,将数据通过管道传输到
cat并返回是完全没有必要的,要使脚本正常工作,您真正需要做的就是通过说$| = 1来禁用缓冲;如果是这样,那应该适用于 Linux 和 Windows。如果cat真的在做一些神奇的事情来解决一个真正的问题,那么您将需要确切地弄清楚问题是什么以及为什么cat解决了它;我们需要更多信息来帮助您。首先向我们展示您的原始脚本是什么样子(在您的同事“修复”它之前)并告诉我们您使用它时出了什么问题。
标签: linux windows perl process stdin