LINUX.ORG.RU

PERL, перехват STDIN и STDOUT одновременно


0

0

Как можно из PERL выполнить программу, сначала слив ей в stdin инфу, а потом получить из её stdout-а результат?

после поисков нарыл такой вариант:
--parent--------
$text="123456789";
use IPC::Open2;
$pid = open2(*CHLD_OUT, *CHLD_IN, $name);
print CHLD_IN $text; #уходят без проблем, ничего не блокируется
close(CHLD_IN);
while (<CHLD_OUT>) {print ;} #отсюда получаем только "t1t2"
close(CHLD_OUT);
--child----------
print "t1";
while(<STDIN>){print ;} #тут пусто
print "t2";
-----------------
частично это работает, т.е. данные из stdout читаются.
но вот с первой частью проблема. данные уходят(ничего не блокируется даже если их много), но вот куда они приходят выяснить пока не удалось. :-(

У меня твой пример не компилится, но в таком виде все работает:

try.pl:
#!/usr/bin/perl
$text="123456789";
use IPC::Open2;
$name="./ch.pl";
$pid = open2(*CHLD_OUT, *CHLD_IN, $name);
print CHLD_IN $text; #уходят без проблем, ничего не блокируется
close(CHLD_IN);
while (<CHLD_OUT>) {print ;} #отсюда получаем только "t1t2"
close(CHLD_OUT);

ch.pl:
#!/usr/bin/perl
print "t1";
while(<STDIN>){print ;} #тут пусто
print "t2";

./try.pl
t1123456789t2

Только надо  лучше буферизацию вывода в клиетне отключить, 
если посерьезнее диалог нужен,
$|=1;

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

> У меня твой пример не компилится, ...

Нет, прошу прощения, я его мышкой неправильно скопировал просто :)

Короче, у меня работает как надо.

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

Чёрт, походу в ActivePerl какие-то нестыковки. :-( Хотелось, чтобы и под m$ работало. Видать не судьба.

TripleGluk
() автор топика
Ответ на: комментарий от Reinventer

>$ perl -e 'open CAT,"| cat"; print CAT "test\n"; print <CAT>;'

то, что выводит 'cat' (в данном случае) надо прочитать, а в примере оно выводиться на консоль.

TripleGluk
() автор топика
Ответ на: комментарий от Die-Hard

>Только надо лучше буферизацию вывода в клиетне отключить, если посерьезнее диалог нужен,

Посерьёзнее - в смысле несколько циклов обмена данными? Не, тут всё тупо: залить, переварить и слить :-) А вобще учту, спасибо.

TripleGluk
() автор топика
Ответ на: комментарий от TripleGluk

try.pl

#!/usr/bin/perl
$text="123456789\n";
use IPC::Open2;
$name="ch.pl";
$pid = open2(*CHLD_OUT, *CHLD_IN, "c:/web/perl/bin/perl.exe", $name);
print CHLD_IN $text; #уходят без проблем, ничего не блокируется
close(CHLD_IN);
while (<CHLD_OUT>) {print ;} #отсюда получаем только "t1t2"
close(CHLD_OUT);

ch.pl

#!/usr/bin/perl
print "t1";
chomp($m1 = <STDIN>);
print $m1;
print "t2";

Так под activeperl работает. Без указания пути к интерпретатору
 или \n - нет. Как это чудо заставить закончить читать в цикле
 - не знаю. Если есть возможность, лучше использовать cygwin.

anonymous
()
Ответ на: комментарий от TripleGluk

> то, что выводит 'cat' (в данном случае) надо прочитать, а в примере оно выводиться на консоль

А разве в твоем случае его не надо прочитать?:
while (<CHLD_OUT>) {print ;}

в моем примере все тоже выводится на консоль.

Или я что-то не понимаю? :)

Reinventer
()
Ответ на: комментарий от Reinventer

Хорошо, давай я нарисую конкретно твой пример:
--- parent.pl ----
#!/usr/bin/perl
$text="123456789";
$name='./child.pl';

open CHLD, "| $name";

print CHLD $text;
print while <CHLD>;
close CHLD;
------------------

---- child.pl ----
#!/usr/bin/perl
print "t1";
while(<STDIN>){print ;} #тут пусто
print "t2";
------------------

./parent.pl
t1123456789t2

Reinventer
()
Ответ на: комментарий от anonymous

Всё! Понял! Спасибо!!!

ЗЫ: а почему без интерпретатора работало только на половину??? Я бы понял, если бы совсем не работало.. :-(

>Как это чудо заставить закончить читать в цикле - не знаю.

Да вроде при закрытии канала сам должен прекращать.. работает же :) с этим ещё буду разбераться.

TripleGluk
() автор топика
Ответ на: комментарий от Reinventer

>А разве в твоем случае его не надо прочитать?: while (<CHLD_OUT>) {print ;}

Нет, я просто выдрал кусок из проги. Она вывод потом отправляет дальше. Попробовал ради интереса этот вариант (продолжительные поиски в сети убедили, что такой халявы вроде быть не должно) - не сработало. всё уходит на консоль, родитель не получает ничего.

TripleGluk
() автор топика
Ответ на: комментарий от TripleGluk

> всё уходит на консоль, родитель не получает ничего.

и правда, пардон, туплю :)

Reinventer
()
Ответ на: комментарий от Reinventer

2Reinventer:

Ты запускаешь пайп в одну сторону, а _думешь_, что 
по нему течет в обе. Просто Перл тебя за нос водит.
Попробуй так изменить свой пример:
#!/usr/bin/perl
$text="123456789";
$name='./child.pl';

open CHLD, "| $name";

print CHLD $text;
#print while <CHLD>;
close CHLD;

и все поймешь: child.pl просто тупо выводит на консоль,
и вывод этот никем не перехватывается; print while <CHLD>;
тут вообще не при чем. 


Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

2Reinventer:

Пардон, слишком долго я тебе отвечал :)

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

>Да. BTW, для этого Open2 и написан...

Ну тут уже синхронизация протоколом нужна...

А буферизация тут действительно imho мешать будет сильно.

TripleGluk
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.