in reply to How to read from shell command and terminate it afterwards?

use IO::Select qw( ); # How long (in seconds) of not getting anything is considered done. use constant TIMEOUT => 2.0; open(my $pipe, '-|', 'mDNS -L "Service Name" _service._tcp domain'); my $buf = ''; # Wait to get something. my $rv = sysread($pipe, $buf, 64*1024, length($buf)); die $! if !defined($rv); # Wait until we stop getting if ($rv) { my $sel = IO::Select->new($pipe); for (;;) { if (!$sel->can_read(TIMEOUT)) { kill KILL => $pid; last; } my $rv = sysread($pipe, $buf, 64*1024, length($buf)); die $! if !defined($rv); last if !$rv; } } close($pipe); print("Got:\n$buf\n");

Replies are listed 'Best First'.
Re^2: How to read from shell command and terminate it afterwards?
by chessgui (Scribe) on Feb 10, 2012 at 07:07 UTC
    If only this would work on Windows. Life would be much simpler.

      You can use a socketpair to create a pipe out of sockets.

      use Socket qw( AF_UNIX SOCK_STREAM PF_UNSPEC ); sub _pipe { socketpair($_[0], $_[1], AF_UNIX, SOCK_STREAM, PF_UNSPEC) or return undef; shutdown($_[0], 1); # No more writing for reader shutdown($_[1], 0); # No more reading for writer return 1; }

      Use that as you would use pipe, then pass the writer end to open3.

      use IPC::Open3 qw( open3 ); open(local *CHILD_STDIN, '<', 'nul:') or die $!; _pipe(\local *FROM_CHILD, \local *CHILD_STDOUT); my $pid = open3('<&CHILD_STDIN', '>&CHILD_STDOUT', '>&STDERR', $cmd); my $pipe = \*FROM_CHILD; ... waitpid($pid, 0);
        I have not tested this as yet, but is this more simple? It looks more complicated.