http://qs321.pair.com?node_id=1165192

rcrews has asked for the wisdom of the Perl Monks concerning the following question:

I am wrapping my head around a new technique today: Use IPC::Open3 instead of backticks. Here is the program I started with:

#!/usr/bin/env perl use 5.016; use autodie; use warnings; our $VERSION = 'v.0.0.1'; say qx[/bin/ls]; exit 0; __END__

It it simple and works. Then I ran perlcritic:

$ perlcritic -1 syscall1.pl Backtick operator used at line 8, column 5. Use IPC::Open3 instead. +(Severity: 3)

I am eager to learn new techniques and become a better Perl programmer. My goal is to update the script to pass the perlcritic test and use other best practices while keeping the code Perlish, readable, maintainable, and reusable. Here's what I came up with:

#!/usr/bin/env perl use 5.016; use autodie; use warnings; use English '-no_match_vars'; use IPC::Open3; use Symbol 'gensym'; use Readonly; our $VERSION = 'v.0.0.2'; say system_ipc_open3('/bin/ls')->{'output'}; sub system_ipc_open3 { my @command = map { split m{\s+}xms } @ARG; Readonly my $SYSCALL_EXIT_STATUS_MASK => 8; Readonly my $BUFFER_SIZE => 2_000_000; my ( $child_in_fh, $child_out_fh, $child_err_fh, $child_in, $child_out, $child_err, $buffer, $child_pid, $child_exit_status ) = q[]; $child_err_fh = gensym; $child_pid = open3( $child_in_fh, $child_out_fh, $child_err_fh, @command ); $child_exit_status = $CHILD_ERROR >> $SYSCALL_EXIT_STATUS_MASK; while ( my $read = sysread $child_out_fh, $buffer, $BUFFER_SIZE ) { $child_out .= $buffer; } while ( my $read = sysread $child_err_fh, $buffer, $BUFFER_SIZE ) { $child_err .= $buffer; } waitpid $child_pid, 0; return { exit_status => $child_exit_status, error => $child_err || q[], output => $child_out || q[], }; } exit 0; __END__

Version 2 is verbose and "low level". My question to the monks: How is this an improvement? Is there a better way to Use IPC::Open3 instead of backticks?