3
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
}

上記のコードは、別のスクリプト (子と呼ばれる) を実行する必要がある、私が書いているスクリプトの一部です。/var/tmp に Cookie ファイルが存在するかどうかによって、子プロセスは入力を求められる場合とされない場合があります (どちらのスクリプトも CentOS5 / perl 5.8.8 で記述されています)。

親が親の STDIN から入力を渡すことができるように、子が入力を待っているかどうか、いつ待っているかを判断する必要があります。また、親が Perl::Critic の残忍な (重大度 1) チェックに合格する必要があるため、open3 を使用して子プロセスを開く必要があります。

コメントを含めたのは、Cookie ファイルが既に設定されている場合、少なくとも親に子を適切に呼び出させることができるためです。その場合、子は入力を待機しないためです。

子供が入力を待っているかどうかを判断する方法の例を見つけようとして、私は周りをチェックしました。私が見つけた 1 つの例では strace ( http://www.perlmonks.org/?node_id=964971 ) を使用していましたが、それは私がやろうとしていることに対して複雑すぎるように感じます。

私を導くためのリンクは大歓迎です。

4

1 に答える 1

3

パイプにスペースがあるかどうかを確認できます ( 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 の存在理由です。
于 2017-01-04T14:20:19.867 に答える