2015-11-10 1 views
4

В Perl один способ чтения STDOUT подпроцесса является использование open:Как читать STDOUT из подпроцесса в OO Perl

open(PIPE, "ls -l |"); 

Я искал более объектно-ориентированный подход к сделайте это, хотя, и я использовал IO::Pipe с некоторым успехом. Однако я хочу обнаружить ошибки, особенно если команда не является исполняемой. Однако я не могу понять, как это сделать через IO::Pipe. Вот что у меня есть:

use strict; 
use warnings; 

use IO::Pipe; 


my($cmd) = join (" ", @ARGV); 

open(PIPE, "$cmd |") || die qq(error opening PIPE); 
while (<PIPE>) { 
     chomp; 
     print "DBG1: $_\n"; 
} 

close PIPE; 

my($pipe) = IO::Pipe->new(); 
$pipe->reader($cmd); 
die qq(error opening IO::Pipe) if $pipe->eof(); 

while (<$pipe>) { 
     chomp; 
     print "DBG2: $_\n"; 
} 

$pipe->close(); 

Если команда подпроцесса является недействительной, обе проверки будет правильно die. Если подпроцесс не производит никакого вывода, хотя, eof() сообщит об ошибке, даже если сама команда отлично:

$ perl pipe.pl "ls -l >/dev/null" 
error opening IO::Pipe at pipe.pl line 20. 

куча вопросов, то:

Есть разумный OO способ читать из подпроцесса в Perl? Является IO::Pipe правильным инструментом для использования? Если да, как я могу проверить, чтобы команда подпроцесса была успешно создана? Если нет, что я должен использовать? Я не хочу писать в подпроцесс, поэтому я не думаю, что хочу IPC::Open2 или IPC::Open3. Я бы предпочел использовать основной модуль, если это возможно.

ответ

0

Backticks не является основным модулем, но, похоже, делает то, что вы ищете.

use strict; 
use warnings; 
use Backticks; 
my $cmd = Backticks->new(join (" ", @ARGV)); 
$cmd->run(); 

if ($cmd->success){ 
     print $cmd->stdout 
} else { 
     print "Command failed\n"; 
} 

Запуск этого с действующей командой, то неправильная команда дает ниже результаты

io_pipe.pl "uname -o"

GNU/Linux 

io_pipe.pl "uname -z"

Command failed 

Обновление Как указано в @thisSuitIsNotBlack, этот модуль изменяет поведение глухих в обратном направлении в perl. Вы должны прочитать раздел «Примечания» в POD. Однако основным из них является то, что необходимо знать:

backticks От Фильтр :: Простой. Источник фильтрации может быть странно иногда ... если вы хотите использовать данный модуль в чисто традиционном стиле Perl OO, просто отключить фильтрацию источника как только вы загрузите модуль:

use Backticks; 
no Backticks; 
+1

По умолчанию Обратные кавычки переопределяет поведение '' \ \ '' используя [источник фильтрации] (https://metacpan.org/pod/Backticks#Source-filtering). Я отключил бы это, поскольку [исходные фильтры, как правило, плохие] (http://stackoverflow.com/questions/1785852/why-are-perl-source-filters-bad-and-when-is-it-ok-to- используй их). Документы рекомендуют использовать Backticks; нет Backticks; ', хотя я все еще пытаюсь обвести голову вокруг того, как это работает. – ThisSuitIsBlackNot

+0

@ThisSuitIsBlackNot - Да, я заметил, что в POD и различные способы восстановления функции backlick perl, но оставил ее для того, чтобы пользователь мог прочитать сам POD. Я предположил, что если он захочет использовать более OO-подход для вызова внешних команд, он будет делать это для всех –

+0

. Я хочу сказать, что ваш примерный код изменяет поведение основного оператора без указания того, что он это делает. Я думаю, что гарантии упоминаются в тексте вашего ответа (или самого кода) вместо того, чтобы быть похороненным в ссылке. – ThisSuitIsBlackNot

3

Проблема не в IO :: Pipe. Проблема eof - неправильный способ проверить ошибку канала. Это не означает, что трубы нет, это значит, что читать от этой трубы. У вас была бы такая же проблема с eof PIPE. Это прекрасно, потому что подпроцесс ничего не печатает.

Если вы хотите проверить, что подпроцесс успешно запущен, выясняется, что IO :: Pipe уже делает это за вас.

# IO::Pipe: Cannot exec: No such file or directory 
$pipe->reader("hajlalglagl");