Reputation: 1306
My bosswrap.pl
will generate arbitrary arrays containing whitespace in the elements. It repeatedly sends the array by a system call to wrapped.pl
, which creates STDOUT based on the array.
Subsequently, bosswrap.pl
must append the STDOUT of wrapped.pl
to a file which bosswrap.pl
controls. That is where I am stuck. First wrapped.pl
:
#!/usr/bin/perl
use strict; use warnings;
print "inside $0\n";
my $countarrayelements=0;
for my $item ( @ARGV ) {
$countarrayelements++;
print "$countarrayelements: |$item|\n";
}
Then bosswrap.pl
:
#!/usr/bin/perl
use strict; use warnings;
my $fileresult = "trash.txt";
unlink $fileresult; # rm any existing file
my $handlefileresult;
my @array = ( 5, "don't you . . . ", "\x09\x21", "\x3f \x21" );
my $count=0;
print "inside $0\n";
for my $element ( @array ) {
$count++;
print "$count\t|$element|\n";
}
#https://stackoverflow.com/questions/50553031/calling-a-shell-command-with-multiple-arguments
#list form: command line arguments pass verbatim, avoid shell interpolation
system("wrapped.pl", @array) == 0 or die "system failed: \$? = $?";
#This block sends the return code, not the STDOUT, to handlefileresult
open( $handlefileresult, ">> ", $fileresult) || die "$0: can't open $fileresult for appending$!";
print $handlefileresult "not a system call\n";
print {$handlefileresult} system("wrapped.pl", @array) == 0 or die "system failed: \$? = $?";
close ( $handlefileresult ) || die;
#In the following block, select unfortunately will not redirect output of system call:
open( $handlefileresult, ">> ", $fileresult) || die "$0: can't open $fileresult for appending$!";
select $handlefileresult;
print "selected; BEFORE system call\n";
system("wrapped.pl", @array) == 0 or die "system failed: \$? = $?";
print "selected; AFTER system call\n";
close ( $handlefileresult ) || die;
Again, I want to repeatedly call wrapped.pl
from inside bosswrap.pl
and put the output of these system calls into $fileresult
.
One reply @ikegami suggested use IPC::Run qw( run );
but that throws an error. I run perl on macos. What has to be done to get this to work?
> perl --version
This is perl 5, version 18, subversion 4 (v5.18.4) built for darwin-thread-multi-2level
(with 2 registered patches, see perl -V for more detail)
Copyright 1987-2013, Larry Wall
Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.
Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl". If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.
> bosswrap.pl
Can't locate IPC/Run.pm in @INC (you may need to install the IPC::Run module) (@INC contains: /sw/lib/perl5/darwin-thread-multi-2level /sw/lib/perl5 /sw/lib/perl5/darwin /Library/Perl/5.18/darwin-thread-multi-2level /Library/Perl/5.18 /Network/Library/Perl/5.18/darwin-thread-multi-2level /Network/Library/Perl/5.18 /Library/Perl/Updates/5.18.4 /System/Library/Perl/5.18/darwin-thread-multi-2level /System/Library/Perl/5.18 /System/Library/Perl/Extras/5.18/darwin-thread-multi-2level /System/Library/Perl/Extras/5.18 .) at /Users/BNW/u/kh/bin/bosswrap.pl line 3.
BEGIN failed--compilation aborted at /Users/BNW/u/kh/bin/bosswrap.pl line 3.
>
Based on What's the easiest way to install a missing Perl module? I did
> cpan IPC::Run
<snip>
Appending installation info to /Users/BNW/perl5/lib/perl5/darwin-thread-multi-2level/perllocal.pod
TODDR/IPC-Run-20180523.0.tar.gz
/usr/bin/make install -- OK
And then rebooted this MacBook Pro 10.14.6. But I get apparently the same error:
> bosswrap.pl
Can't locate IPC/Run.pm in @INC (you may need to install the IPC::Run module) (@INC contains: /sw/lib/perl5/darwin-thread-multi-2level /sw/lib/perl5 /sw/lib/perl5/darwin /Library/Perl/5.18/darwin-thread-multi-2level /Library/Perl/5.18 /Network/Library/Perl/5.18/darwin-thread-multi-2level /Network/Library/Perl/5.18 /Library/Perl/Updates/5.18.4 /System/Library/Perl/5.18/darwin-thread-multi-2level /System/Library/Perl/5.18 /System/Library/Perl/Extras/5.18/darwin-thread-multi-2level /System/Library/Perl/Extras/5.18 .) at /Users/BNW/u/kh/bin/bosswrap.pl line 3.
BEGIN failed--compilation aborted at /Users/BNW/u/kh/bin/bosswrap.pl line 3.
>
How can I fix this?
Upvotes: 2
Views: 550
Reputation: 1306
After installing IPC::Run
with the help of http://triopter.com/archive/how-to-install-perl-modules-on-mac-os-x-in-4-easy-steps/, the following solution from https://stackoverflow.com/users/589924/ikegami worked:
#!/usr/bin/perl
use strict; use warnings;
use IPC::Run qw( run );
my $fileresult = "trash.txt";
unlink $fileresult; # rm any existing file
my @array = ( 5, "don't you . . . ", "\x09\x21", "\x3f \x21", "\x09*\x09" );
my $count=0;
print "inside $0\n";
for my $element ( @array ) {
$count++;
print "$count\t|$element|\n";
}
run [ "wrapped.pl", @array ], '>>', $fileresult;
die("wrapped.pl killed by signal ".( $? & 0x7F )."\n") if $? & 0x7F;
die("wrapped.pl exited with error ".( $? >> 8 )."\n") if $ ?>> 8;
exit 0;
Upvotes: 1
Reputation: 386361
STDOUT
and Perl's default output handle (as set using select
) are process-specific variables the OS knows nothing of. An executed program does not inherit these. It does inherit the parent's file descriptors, the underlying system handles.
I would let IPC::Run or IPC::Run3 do the hard work for me.
use IPC::Run qw( run );
run [ "wrapped.pl", @array ],
'>>', $fileresult;
die("wrapped.pl killed by signal ".( $? & 0x7F )."\n") if $? & 0x7F;
die("wrapped.pl exited with error ".( $? >> 8 )."\n") if $ ?>> 8;
It is also possible to do with low-level core module IPC::Open3
use IPC::Open3 qw( open3 );
open(local *CHILD_STDIN, '<', '/dev/null')
or die("Can't open \"/dev/null\": $!\n");
open(local *CHILD_STDOUT, '>>', $fileresult)
or die("Can't append to \"$fileresult\": $!\n");
my $pid = open3('<&CHILD_STDIN', '>&CHILD_STDOUT', '>&STDERR',
"wrapped.pl", @array);
waitpid($pid, 0);
die("Can't execute wrapped.pl: $!\n") if $? == -1;
die("wrapped.pl killed by signal ".( $? & 0x7F )."\n") if $? & 0x7F;
die("wrapped.pl exited with error ".( $? >> 8 )."\n") if $ ?>> 8;
Upvotes: 2