IPC::Open2 and IPC::Open3

I love Open2 because it cleanly does something that I actually need to do a fair bit: filter using an external command.

    use IPC::Open2;

    $pid = open2( \*RDRFH, \*WTRFH, 'some cmd and args' );      ## or
    $pid = open2( \*RDRFH, \*WTRFH, 'some', 'cmd', 'and', 'args' );

    my ( $rdrfh, $wtrfh );
    $pid = open2( $rdrfh, $wtrfh, 'some cmd and args' );        ## or
    $pid = open2( $rdrfh, $wtrfh, 'some', 'cmd', 'and', 'args' );

You can now write to $wtrfh and read from $rdrfh like normal filehandles. And you can read and write repeatedly and non-sequentially.

However... be extremely careful. It's tremendously easy to find yourself in deadlock if you don't check your input, etc.

IPC::Open3

Also opens a filehandle for STDERR, or you can **probably smarter** bind this to local \*STDERR. Reading from the ERROR filehandle is guaranteed to cause deadlock. You can always Fcntl flag it as non-block, or IO::Select it, though.

    my($wtr, $rdr, $err);
    $pid = open3($wtr, $rdr, $err,
                    'some cmd and args', 'optarg', ...);
    $pid = open3($wtr, $rdr, \*STDERR,
                    'some cmd and args', 'optarg', ...);

If this needs to be super-safe, then you are best to wrap the open in an eval {}, and likely also set an alarm in the eval to prevent deadlock and create a $SIG{PIPE} handler with a wait to prevent zombies. And follow the IO::Select advice for both reading output and error.

That might sound like a lot to worry about, but as IPC goes, it's pretty par for the course.

Links