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.
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.