Вместо потоков и `` используйте:
open my $fh, '-|', 'some_program --with-options';
Таким образом, откройте несколько файловых дескрипторов (столько программ, сколько вам нужно запустить), а затем используйте IO::Select
для опроса данных из них.
Упрощенный пример.
Предположим, у меня есть скрипт оболочки, который выглядит следующим образом:
=> cat test.sh
#!/bin/bash
for i in $( seq 1 5 )
do
sleep 1
echo "from $$ : $( date )"
done
это может выглядеть так:
=> ./test.sh
from 26513 : Fri Aug 7 08:48:06 CEST 2009
from 26513 : Fri Aug 7 08:48:07 CEST 2009
from 26513 : Fri Aug 7 08:48:08 CEST 2009
from 26513 : Fri Aug 7 08:48:09 CEST 2009
from 26513 : Fri Aug 7 08:48:10 CEST 2009
Теперь давайте напишем multi-test.pl
:
#!/usr/bin/perl -w
use strict;
use IO::Select;
my $s = IO::Select->new();
for (1..2) {
open my $fh, '-|', './test.sh';
$s->add($fh);
}
while (my @readers = $s->can_read()) {
for my $fh (@readers) {
if (eof $fh) {
$s->remove($fh);
next;
}
my $l = <$fh>;
print $l;
}
}
Как видите, нет ни вилок, ни ниток. И вот как это работает:
=> time ./multi-test.pl
from 28596 : Fri Aug 7 09:05:54 CEST 2009
from 28599 : Fri Aug 7 09:05:54 CEST 2009
from 28596 : Fri Aug 7 09:05:55 CEST 2009
from 28599 : Fri Aug 7 09:05:55 CEST 2009
from 28596 : Fri Aug 7 09:05:56 CEST 2009
from 28599 : Fri Aug 7 09:05:56 CEST 2009
from 28596 : Fri Aug 7 09:05:57 CEST 2009
from 28599 : Fri Aug 7 09:05:57 CEST 2009
from 28596 : Fri Aug 7 09:05:58 CEST 2009
from 28599 : Fri Aug 7 09:05:58 CEST 2009
real 0m5.128s
user 0m0.060s
sys 0m0.076s