如何从调用它的perl程序中查看正在运行的程序的STDOUT?

slm*_*slm 6 io perl file-io exec parent-child

我们试图弄清楚如何在perl脚本中运行java应用程序,但仍然可以定期从java应用程序的STDOUT中读取.

print "running dcmrcv.bat\n";

open my $fh_dcmrcv, "-|", 'z:\apps\dcm4che\dcm4che-2.0.26\bin\dcmrcv.bat \
  DCMRCV:11112 -dest z:\dcmrcv -journal z:\dcmrcv', 
  or die "could not execute dcmrcv: $!";

print "dcmrcv.bat started\n";
Run Code Online (Sandbox Code Playgroud)

我们希望能够每隔几分钟从文件句柄$ fh_dmcrcv中读取,或者可能通过在文件句柄上存在活动时设置AnyEvent io触发器来读取.

但是,当我尝试从文件句柄中读取时,如果我使用这样的东西,它就会阻塞:

foreach my $line (<$fh_dmcrcv>) {
  print $line;
}
Run Code Online (Sandbox Code Playgroud)

我们已经尝试了几种方法,不要以为我们可以使用File :: Tail,因为模块似乎需要一个实际的文件.问题似乎是$ fh_dcmrcv在我们阅读时阻止了我们,并不确定如何实现我们想要的正确方法.

编辑#1

当我们运行perl脚本时,我们看到的输出如下:

Z:\projects\demo_2>process_files.pl
running dcmrcv.bat
dcmrcv.bat started
Start Server listening on port 11112
11:55:13,495 INFO   - Start listening on 0.0.0.0/0.0.0.0:11112
Run Code Online (Sandbox Code Playgroud)

脚本process_files.pl正在发出消息:

running dcmrcv.bat
dcmrcv.bat started
Run Code Online (Sandbox Code Playgroud)

消息.从java程序是:启动服务器监听端口11112 11:55:13,495 INFO - 开始监听0.0.0.0/0.0.0.0:11112

在这种情况下,我们只是为了这个问题回应那些,我们真的想定期解析某些msgs.并且从不回应他们中的任何一个.

任何见解都表示赞赏,

萨姆

mob*_*mob 4

大多数系统都支持 4 参数select函数(也很好地封装在IO::Select),它可以告诉您套接字句柄或管道句柄上是否有输入等待。在 Windows 中,select仅在套接字上受支持,这导致了这个拜占庭解决方案:

  1. 创建套接字对
  2. Fork 并在子进程中运行命令
  3. 在子进程中,检索命令输出并将其写入套接字
  4. 在父级中,根据需要对套接字使用选择和读取操作

例子:

use Socket;
use IO::Select;
use Time::HiRes;
$cmd = $^X . ' -MMath::BigInt -e "$_=1; '
       . 'print qq/$_!=/,Math::BigInt->new($_)->bfac(),qq/\n\n\n/'
       . ' for 4000..4100"';
socketpair A,B,AF_UNIX,SOCK_STREAM,PF_UNSPEC;  # step 1
if (fork() == 0) {
    open my $fh, '-|', $cmd;                   # step 2
    while (<$fh>) {
        print B;                               # step 3
    }
    close $fh;
    exit $? >> 8;
}
$s = IO::Select->new();
$s->add(\*A);
for (;;) {
    if ($s->can_read(0.25)) {                  # step 4
        $line = <A>;
        print "Do something with command output: $line";
    } else {
        print "No output now. Could be doing something else ...\n";
        Time::HiRes::sleep(0.25);
    }
}
Run Code Online (Sandbox Code Playgroud)

您确定不想将命令输出写入临时文件吗?