LINUX.ORG.RU

Perl, autoflush и потоки

 , , ,


0

1

Есть управляющее приложение (control.pl)

#!/usr/bin/perl
use IPC::Open2;
use IO::Handle;

open2(OUT,IN,"./app.pl");
$| = 1;
IN->autoflush(1);
while ($cmd !~ /^quit$|^q$/) {
  print ">";
  $cmd = <STDIN>;
  # обработка $cmd
  print IN $cmd."\n";
  #close IN;
  $res = <OUT>;
  print "Response: $res\n";
}
close IN;
close OUT;
И обрабатывающее (app.pl)
#!/usr/bin/perl

while (!$exit) {
    $req=<STDIN>;
    # тут будет обработка
    print "APP: get $req \n";
    if ($req =~ /^quit$|^q$/) {$exit = 1;}
}

Суть: команда, введённая с клавиатуры отправляется к скрипту app.pl. Там она обрабатывается и приходит ответ, который вываливается в stdout.
Проблема: команда отправляется на внешний скрипт, только если раскомментировать

# close IN
А это не желательно, так как этот поток нужен для следующих команд. Несколько раз запускать app.pl не вариант, autoflush не работает. Подскажите ЧЯДНТ или обходное решение.

★★★★★

Последнее исправление: crutch_master (всего исправлений: 2)
Ответ на: комментарий от bvn13

Это работает для файла, а не для процесса.

crutch_master ★★★★★
() автор топика
# Зачем подключать IO::Handle если в коде пишешь "print IN"?
IN->autoflush(1);
IN->print($cmd ."\n");
outtaspace ★★★
()

master.pl

#!/usr/bin/perl

use Mojo::Base -strict;
use IO::Handle;
use IPC::Open2 'open2';

my ($CHILD_OUT, $CHILD_IN);
open2($CHILD_OUT, $CHILD_IN, 'perl ./slave.pl');

my ($in, $out) = (IO::Handle->new, IO::Handle->new);

map { $_->autoflush(1) } $in, $out;

$in->fdopen($CHILD_IN,   'w');
$out->fdopen($CHILD_OUT, 'r');

for my $count (1 .. 10) {
    $in->print($count ."\n") and sleep 1;

    print $out->getline;
}

slave.pl

#!/usr/bin/perl

use Mojo::Base -strict;
use IO::Handle;

my ($in, $out) = (IO::Handle->new, IO::Handle->new);

map { $_->autoflush(1) } $in, $out;

$in->fdopen(fileno(STDIN),   'r');
$out->fdopen(fileno(STDOUT), 'w');

while (my $line = $in->getline) { $out->print('from slave: '. $line); }
outtaspace ★★★
()
Ответ на: комментарий от outtaspace

Получилось следующее:

#!/usr/bin/perl
# control.pl
use IPC::Open2;

open2(OUT,IN,"./app.pl");
$|=1;

while ($cmd !~ /^quit$|^q$/) {
  print ">";
  $cmd = <STDIN>;
  print IN $cmd;
  $res = <OUT>;
  print "Response: $res\n";
}
close IN;
close OUT;

#!/usr/bin/perl
# app.pl
$|=1;
while (!$exit) {
    $req=<STDIN>;
    print "APP: get $req ";
    if ($req =~ /^quit$|^q$/) {$exit = 1;}
}

Вроде как часы.

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

Как вариант сойдет, мой тоже работает, скорее демонстрирует как можно грубо писать на IO::Handle (раз уж ты его добавил в код).

Зачем «while» с условием «not $exit»? Можно выходить из «while» через «last», при этом в «while» ожидая данных из STDIN.

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

Да, это всё так - минималистский пример. В целом всё гораздо хуже.

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