IPC::Open3 и определение, ждет ли ребенок ввода

sub run_command
{
    my $COMMAND         = shift;
    my @OUTPUT;
    my %CMD             = {};

    $CMD{pid}           = open3(my $CH_IN, my $CH_OUT, my $CH_ERR, $COMMAND);
    $CMD{_STDIN}        = $CH_IN;
    $CMD{_STDOUT}       = $CH_OUT;
    $CMD{_STDERR}       = $CH_ERR;

    my $line            = readline $CMD{_STDOUT};
    print $line;

#    open my $CMDPROC, q{-|}, $COMMAND   or return;
#    foreach (<$CMDPROC>)
#    {
#        push @OUTPUT, "$ARG";
#    }
    close $CMDPROC                      or return;

    return @OUTPUT
}

Приведенный выше код является частью сценария, который я пишу, который должен запускать другой сценарий (называемый дочерним). Ребенок может или не может запрашивать ввод, в зависимости от наличия файла cookie в /var/tmp (оба сценария написаны на CentOS5 / perl 5.8.8)

Мне нужно определить, когда и когда ребенок ждет ввода, чтобы родитель мог передать ввод из STDIN родителя. Мне также нужно использовать open3, чтобы открыть дочерний процесс, так как мне нужно, чтобы parent прошел жестокую (Severity 1) проверку Perl::Critic.

Я включил комментарии, потому что, когда файл cookie уже установлен, я могу, по крайней мере, заставить родителя правильно вызывать child, так как child не ждет ввода в этом случае.

Я проверял, пытаясь найти примеры того, как определить, ждет ли ребенок ввода. Один пример, который я нашел, использовал strace ( http://www.perlmonks.org/?node_id=964971), и я чувствую, что это может быть слишком сложно для того, что я пытаюсь сделать.

Любые ссылки, чтобы направлять меня будет принята с благодарностью.

1 ответ

Решение

Вы можете проверить, есть ли место в трубе (используя select). Вы даже можете проверить, сколько места доступно в трубе. Однако я никогда не слышал о возможности проверить, заблокирован ли поток, ожидающий чтения из канала. Я думаю, вы должны изучить другие пути.


Мне кажется, что программа, которая читает из STDIN только при выполнении определенных условий, не связанных с аргументами, выдаст подсказку, указывающую, что она ожидает ввода. Если это так, можно использовать Expect для запуска и управления дочерней программой.

Но самое простое решение - записать данные в STDIN безоговорочно. Реализация этого с использованием IPC::Open3 очень сложна[1], поэтому я рекомендую перейти на IPC:: Run3 (проще) или IPC:: Run (более гибко).

# Capture's child's STDERR
run3 [ $prog, @args ], \$text_for_stdin, \my $text_from_stdout, \my $text_from_stderr;

или же

# Inherits parent's STDERR
run3 [ $prog, @args ], \$text_for_stdin, \my $text_from_stdout;

  1. Когда вы оба пишете в STDIN ребенка и читаете из STDOUT ребенка, вы должны использовать select (или что-то еще), чтобы избежать тупиков. IPC::Open3 очень низкого уровня и не делает этого для вас, тогда как для этого используются IPC:: Run3 и IPC::Run raison d'être.
Другие вопросы по тегам