【问题标题】:Write text to pipe and read result never completes将文本写入管道并读取结果永远不会完成
【发布时间】:2018-01-03 21:32:45
【问题描述】:

我编写了一个 Perl 程序,它打开一个到 xargs 的管道,以便它从输入中读取并在每一行输入中运行一个命令。

我需要读取该管道的输出。

我使用open3,然后将输入写入输入文件句柄。然后循环从输出文件句柄中读取。

但是当它打印我希望看到的最后一行时,它只是挂起并且没有完成该过程。

这是脚本的摘录

my $classNamesOutput = `classNamesInArchive $opt_archive`;

my $pid = open3( \*CHILD_IN, \*CHILD_OUT, false, "xargs -n1 listJavaClassRefs -p $opt_archive -c" );
print "pid[" . $pid . "]\n";

print CHILD_IN $classNamesOutput;

my $output = '';
my $matchingArchiveNames = '';

while ( my $row = <CHILD_OUT> ) {
    chomp $row;
    print "row[" . $row . "]\n";

    if ( $onlyListingMatches == 1 && $row eq $opt_className ) {
        print $opt_archive;
        last;
    }

    if ( $onlyListingMatches == 0 ) {
        $output .= $row . "\n";
    }
}

print "Past loop.\n";

它从不打印Past loop:它只是挂在我认为被调用脚本会产生的输出的最后一行。

【问题讨论】:

  • 我的编辑是否正确地反映了您的问题?请不要将所有内容都个性化。
  • 你从哪里得到open3?你有use 没有提到的模块吗?
  • 除了您询问的问题之外,您的程序还存在 shell 命令注入错误。 "xargs -n1 listJavaClassRefs -p $opt_archive -c" 应该是 "xargs", "-n1", "listJavaClassRefs", "-p", $opt_archive, "-c"
  • 除了您询问的问题外,您的程序还存在竞争条件。如果您想要双向通信,请避免使用open3(因为您随后也需要开始使用 IPC::Select,这会变得非常复杂)。相反,请使用 IPC::Run3 或 IPC::Run。
  • @Borodin 我不知道您所说的“个性化”是什么意思。我从 cpan 得到了 open3。我还能从哪里得到它?

标签: perl


【解决方案1】:

你需要在while循环之前关闭writer:

close CHILD_IN;

编辑:您需要关闭 xargs 的管道(但不是一般情况)的原因是 xargs 显然在输入完成之前不会启动任何进程。这可以通过运行cat | xargs echo 看到:

cat | xargs echo
asdf
asd
faw
seas
eryawr
yawr
ya
ryhs
rhy
erh
< I press Ctrl-d here to terminate pipe >
asdf asd faw seas eryawr yawr ya ryhs rhy erh

对于非 xargs 程序,关闭管道或至少刷新它可能仍然是一个好主意,因为可能会有字节卡在某个级别的缓冲区中。

【讨论】:

  • 请详细说明您的建议
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-06
  • 1970-01-01
  • 1970-01-01
  • 2017-01-27
  • 1970-01-01
相关资源
最近更新 更多