Я хочу проанализировать вывод внешней программы (некоторая команда оболочки) по строкам с помощью Perl. Команда запускается непрерывно, поэтому я помещаю ее в поток и использую общие переменные для связи с моей основной программой.Избегайте буферизации при анализе stdout с помощью Perl
До сих пор мой код похож на
#!/usr/bin/perl
use warnings;
use strict;
use threads;
use threads::shared;
my $var :shared; $var="";
threads->create(
sub {
# command writes to stdout each ~100ms
my $cmd = "<long running command> |";
open(README, $cmd) or die "Can't run program: $!\n";
while(<README>) {
my $line = $_;
# extract some information from line
$var = <some value>;
print "Debug\n";
}
close(README);
}
);
while(1) {
# evaluate variable each ~second
print "$var\n";
sleep 1;
}
Для некоторых команд это работает прекрасно, а линии обрабатываются так же, как они приходят в выходе будет выглядеть следующим образом:.
...
Debug
Debug
...
<value 1>
...
Debug
Debug
...
<value 2>
...
Однако для других команд это ведет себя странно, и строки обрабатываются блочно. Таким образом, $var
не обновляется, и Debug
не печатается ни на какое-то время. Затем, внезапно выход (аналог):
...
<value 1>
<value 1>
<value 1>
...
Debug
Debug
Debug
...
<value 20>
и $var
устанавливается до последнего/текущего значения. Затем это повторяется. Разбор всегда задерживается и выполняется в блоках, а $var
не обновляется между ними.
Прежде всего: есть ли какой-либо лучший/удобный способ для анализа вывода внешней программы (по очереди!), Кроме того, используя трубку?
Если нет, то как я могу избежать такого поведения?
Я прочитал, что с помощью autoflush(1);
или $|=1;
может быть решением, но только для «выбранного выходного канала». Как я могу использовать это в моем контексте?
Заранее спасибо.
Это «долго работает команда» выход "s, который не покраснел. Есть утилита под названием «unbuffer», которая обманывает программы, которые используют соглашение буферизации строк при подключении к терминалу. – ikegami
Есть ли способ контролировать поведение промывки команды? Но команда печатает каждые 100 мс до'stdout '. Где разница между shell stdout и трубопроводом на perl? – raidlman
Я бы посмотрел на выполнение длинной команды из командной строки и трубопровода на 'perl -n script'. – marneborn