2016-10-09 4 views
1

Я спросил о IPC :: Open3 в this question. Однако у меня все еще возникают проблемы.Больше проблем с IPC :: Open3

Этот код висит, а не ждет, пока EOF не появится на stdin. Он также не пишет ничего для stderr.

Это не дубликат, потому что этот вопрос задает вопрос о захвате вывода, в то время как этот вопрос задает вопрос о вводе.

#!/usr/bin/env perl 

use strict; 
use warnings; 
use utf8; 
use v5.10; 

use IPC::Open3; 

use Symbol 'gensym'; 

my $output; 
# pipe my $input, $output or die $!; 
my $pid = open3(\*STDIN, $output, \*STDERR, 'sh', 
    '-c', 'echo 1 >&2; cat /usr/include/unistd.h -') or die $!; 


while (<$output>) { 
    say $output; 
} 
waitpid $pid, 0; 
+0

Это звучит как проблема [X Y] (http://xyproblem.info/). Можете ли вы объяснить, что именно вы в конечном итоге пытаетесь сделать? Похоже, что часть того, что вы хотите сделать, - это выполнить команду оболочки и захватить ее STDERR и STDOUT и отобразить STDOUT для просмотра пользователем. Вы также хотите взять STDIN из скрипта, чтобы отправить его в команду оболочки? – dasgar

+0

Если вы хотите просто захватить STDERR и STDOUT из командной строки, вы можете проверить функцию захвата с [Capture :: Tiny] (https://metacpan.org/pod/Capture::Tiny). Это позволит вам захватить STDERR, STDOUT и код выхода. Если вы также хотите отображать STDOUT, а также захватывать STDERR и STDOUT, возможно, одна из функций tee от Capture :: Tiny будет работать для вас. – dasgar

+0

@ikegami Я отредактировал этот вопрос, чтобы объяснить, почему это не дубликат. – Demi

ответ

1

Вашей программа страдает от следующих проблем:

  • \*STDIN (открыть STDIN как трубы, привязанных к STDIN ребенку) должен быть <&STDIN (используйте родитель STDIN как ребенок STDIN).
  • \*STDERR (открыть STDERR как трубы, привязанных к ребенку STDERR) должен быть >&STDERR (используйте родитель STDERR как ребенок STDERR).
  • say $output; должно быть say $_; или просто say;.
  • Вы используете say, но значение, которое вы печатаете, уже завершено в новой строке. Сначала используйте chomp или переключитесь на использование print.
  • open3 не является системным вызовом, поэтому он не устанавливает $!.
  • open3 не возвращает false при ошибке; он выдает исключение.

Обратите внимание, что если вы передадите один скаляр в качестве команды, он будет передан в sh -c.

#!/usr/bin/env perl 

use strict; 
use warnings; 
use v5.10; 

use IPC::Open3 qw(open3); 

my $pid = open3('<&STDIN', my $output, '>&STDERR', 
    'echo 1 >&2; cat /usr/include/unistd.h -'); 

while (<$output>) { 
    chomp; 
    say "<$_>"; 
} 

waitpid($pid, 0);