Я создал простой скрипт обработки текста на работе, который будет использоваться другой программой. Когда я закончил, кто-то вспомнил, что скрипт не должен блокировать STDIN / STDOUT, чтобы инструмент, использующий его, работал правильно, и изменил скрипт соответствующим образом. Скрипт открывает cat
* nix в подпроцессе через IPC::Open2
и печатает в него STDIN, читает его обратно. а затем обрабатывает и распечатывает его в STDOUT. Я понятия не имею, как это делает скрипт неблокирующим, но, видимо, он работал.
Я хотел, чтобы она работала и в Windows, поэтому заменил cat
на type CON
, простую команду Windows для печати STDIN. Ниже приведен пример сценария:
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
заменяет более сложную программу. Оператору OP сказали, что передача данных вcat
и обратно делает скрипт неблокирующим. Я совершенно уверен, что это ерунда. - person Harry Johnston   schedule 17.06.2015cat
и обратно совершенно не нужно, и все, что вам действительно нужно было сделать, чтобы скрипт заработал, - это отключить буферизацию, сказав$| = 1
; Если да, то это должно работать как в Linux, так и в Windows. Еслиcat
действительно творит что-то волшебное, решающее реальную проблему, вам нужно будет точно выяснить, в чем проблема и почемуcat
исправляет ее; нам понадобится дополнительная информация, чтобы помочь вам в этом. Для начала покажите нам, как выглядел ваш исходный сценарий (до того, как его исправил ваш коллега), и расскажите, что идет не так, когда вы его используете. - person Harry Johnston   schedule 17.06.2015print while(<STDIN>)
и$|++; print while(<STDIN>)
? Кажется, что они оба печатаются сразу после получения одной строки, без каких-либо проблем с буферизацией. - person Nate Glenn   schedule 17.06.2015