How to see the running STDOUT program from the perl program that called it?

We are trying to figure out how to start a Java application from a perl script, but still you can periodically read from a STDOUT Java application.

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"; 

We wanted to be able to read $ fh_dmcrcv from the file descriptor every few minutes, or perhaps configure the AnyEvent io trigger when there is activity in the file descriptor.

However, when I try to read from a file descriptor, it blocks if I use something like this:

 foreach my $line (<$fh_dmcrcv>) { print $line; } 

We tried several approaches, we don’t think that we can use File :: Tail, since it seems that the module needs an actual file. The problem is that $ fh_dcmrcv is blocking us when we read from it, I'm not quite sure about the right approach to how to achieve what we want.

EDIT NO. 1

When we run our perl script, we see the output as follows:

 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 

script, process_files.pl emits msgs .:

 running dcmrcv.bat dcmrcv.bat started 

msgs. from the java program: Start the server listening on port 11112 11: 55: 13,495 INFO - Start listening on 0.0.0.0/0.0.0.0:11112

In this case, we echo them only for the sake of this issue, so we want to periodically analyze certain messages. and never repeat them.

Any understanding is understood

-Sam

+6
source share
3 answers

Most systems support a function with 4 select arguments (also well packaged in IO::Select ), which can tell you if there is an input waiting on sockethandle or pipehandle. On Windows, select is only supported on sockets, which leads to this Byzantine solution:

  • Create a pair of sockets
  • Fork and run a command in a child process
  • In the child process, extract the output of the command and write it to the socket
  • In the parent block, use the select and read operations on the socket as desired.

Example:

 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); } } 

Are you sure you don't want to just write your command output to a temp file?

+4
source

Use IO :: Select or four-argument select() to read when reading will not block. EDIT : Nevermind, you're on Windows , so this will not work. One option is to have an intermediate process read from this channel and store an intermediary file filled only with any tail length that you need. Bleh.

However, the best way to read "every few minutes" from a pipe is to read every few seconds.

+2
source

Try reading instead:

 while (my $line = <$fh_dmcrcv>) { print $line; } 

considers

0
source

Source: https://habr.com/ru/post/908057/


All Articles