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 传递输入。我还需要使用 open3 打开子进程,因为我需要父进程通过 Perl::Critic 的残酷(严重性 1)检查。

我包括了评论,因为当cookie文件已经设置时,我至少可以让父母正确地调用孩子,因为在这种情况下孩子不会等待输入。

我四处检查试图找到如何确定孩子是否正在等待输入的示例。我发现的一个例子使用了 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 raison d'être。
于 2017-01-04T14:20:19.867 回答