# Uses RunPipe_PerlMonks module to run and trap failures in piped commands. use strict; use warnings; use lib "/PATH_TO_RunPipe_PerlMonks"; use RunPipe_PerlMonks; # Here we pass a series of piped cmds to be run by IPC::Run. # The 3rd cmd, "grep zzzzzzzz", will fail. Goal is to identify it as the cmd that made the series fail (a normal system call only gets the status of the last cmd, which in this case is a (false) success). my @cmds = ( ['sort'], ['uniq', '-c'], [qw(grep zzzzzzzz)], ['sort', '-rnk1'] ); my $rp = new RunPipe_PerlMonks('cmds' => \@cmds); # This will open the FH for the cmd, like "open FH_GLOB, '|-', 'sort | uniq -c ...'", but it must be done by IPC::Run::start() since we're using it to run the cmds. Must be done before passing data to the FH. $rp->start(\*FH_GLOB); ####### Now pump some data to the FH ###### my $max = 5; for (my $i = 0; $i < $max; $i++) { print FH_GLOB int(rand($max)) . "\n"; } close FH_GLOB; ############################################# # Get the FH that will contain the output so we can process it in real time (rather than waiting for everything to finish first). my $fh = $rp->fh; # or die "Error: \$rp->fh not defined.\n"; # This forks. The parent returns to the main program (i.e. here) immediately so we can process the results while waiting for them to finish. The child calls $ipc_run_h->finish(), which waits for all cmds (i.e. children) to finish. It doesn't work because it's a child waiting for another child. Is there a better way to do this? $rp->run(); while (my $line = <$fh>) { # do something with each output line. print $line; } close $fh; my $failed_cmd = RunPipe_PerlMonks::failed_cmd; # Important: we want to identify the exact cmd that failed in a series of piped cmds. A normal system call only returns the status of the last cmd. This is why we're using IPC::Run. if (defined $failed_cmd) { print "Failed! cmd = '$failed_cmd'\n"; }