Моя задача - запустить программу из perl и сохранить поток управления для начальной задачи, а также захватить вывод программы в скалярных переменных. Сценарий должен использовать только модули perl, доступные в базовом пакете perl.Perl-дескриптор файла со скалярной целью и IPC :: Open3
Мой первый подход был
use POSIX;
use IPC::Open3;
use strict;
my ($invar, $outvar, $errvar, $in, $out, $err, $pid, $pidr);
open($in, "<",\$invar);
open($out, ">",\$outvar);
open($err, ">",\$errvar);
my $cmd = "sleep 5; echo Test; sleep 5; echo Test; sleep 5;";
$pid = open3($in, $out, $err, $cmd);
my $num = 0;
for($pidr = $pid; $pidr >= 0;)
{
sleep(1) if ($pidr = waitpid($pid, WNOHANG)) >= 0;
print "$num: $outvar" if $outvar;
++$num;
}
close($in);
close($out);
close($err);
При запуске ничего не происходит. Вывод запущенной программы не входит в $outvar
. Для того, чтобы проверить, если моя основная идея терпит неудачу, я попытался это:
my $outvar = "";
my $out;
open($out, ">", \$outvar);
print $out "Test\n";
print "--1--\n$outvar";
print $out "Test2\n";
print "--2--\n$outvar";
который правильно выводит, как и ожидалось:
--1--
Test
--2--
Test
Test2
Возникает вопрос: почему выше программа не работает в качестве тестового примера и вывода текста который должен быть в $outvar
?
Рабочий раствор является гораздо более сложным (при добавлении все проверки безопасности, оставленные из этого примера):
use POSIX;
use IPC::Open3;
use strict;
my ($invar, $outvar, $errvar, $in, $out, $err, $pid, $pidr);
open($in, "<",\$invar);
open($out, ">",\$outvar);
open($err, ">",\$errvar);
my $cmd = "sleep 5; echo Test; sleep 5; echo Test; sleep 5;";
$pid = open3($in, $out, $err, $cmd);
my $num = 0;
for($pidr = $pid; $pidr >= 0;)
{
sleep(1) if ($pidr = waitpid($pid, WNOHANG)) >= 0;
my $obits; vec($obits, fileno($out), 1) = 1;
if(select($obits, undef, undef, 0) > 0)
{
my $buffer;
sysread($out, $buffer, 10240);
print "$num: $buffer" if $buffer;
}
++$num;
}
close($in);
close($out);
close($err);
Он правильно печатает (как должен сделать первый и аналогичным образом):
5: Test
10: Test
Для примеров я удалил большую часть обработки ошибок и аналогичный код для STDERR.
Кстати, это называется «дескриптором файла» (поскольку он держится на системном ресурсе), а не «обработчиком файлов» (поскольку он ничего не обрабатывает, так как это не код). – ikegami