in reply to capture stdout and stderr from external command

The simplest solution that pops into my mind is a piped open. I haven't tried this on windows but it doesn't do anything fancy:
#!/usr/bin/env perl use warnings; use strict; my %cmds; my ($count, $limit, $actmax) = (0, 10, 2); my ($cmdline) = 'sleep 1; echo BOOM'; # I think this command will work in Windows but not sure... sub spawncmd { my ($cmd) = @_; my $pid = open(my $of, '-|', $cmd) or die "open: $!"; ++$count; $cmds{$pid} = $of; warn "Spawned $pid"; return $pid; } sub cleancmd { my ($pid) = @_; die "error: unknown cmd pid: $pid" unless(exists $cmds{$pid}); my $of = delete $cmds{$pid}; print "$pid: $_" while(<$of>); close($of); } spawncmd($cmdline) for(1 .. $actmax); while(keys(%cmds) > 0){ my $pid = waitpid(-1, 0); die sprintf("error: pid $pid had exit code %d", $? >> 8) if($? != +0); cleancmd($pid); spawncmd($cmdline) if($count < $limit); }

This simplifies things by blocking until one of the running commands exits, then reading the command's output all at once before closing the pipe. Standard output and error streams are read together and not separated with a piped open. You didn't specify whether you wanted them together or separate. Parallel processing seems unnecessary in this situation but maybe you have performance requirements you didn't mention.

Replies are listed 'Best First'.
Re^2: capture stdout and stderr from external command
by Eliya (Vicar) on Nov 12, 2011 at 00:33 UTC
    ...reading the command's output all at once before closing the pipe.

    The problem with this approach is if the pipe's buffer should fill up, you have a deadlock (i.e. the spawned program doesn't exit because it waits for the buffer to be emptied, but this won't happen because you wait for the program to exit).  Replace echo BOOM with perl -e"print q(x)x1e5" and you can observe the effect.

      Ah yes you are right. I modified it to use IO::Select before I remembered that select doesn't work in Windows... please disregard my post.

      edit: perlport also says piped opens (i.e. with '|-') don't work on windows. doh!