After dinking around with an expensive three or four days trying to understand IPC::Open3 and trying to make things work I finally got it to work. I thought I would add my 2 cents and hopefully save someone else (or myself somewhere down the road) the same headache.
Yes, I know about IPC::Run. Unfortunately, the host I was required to use did not have it installed and I was not allowed to install any but my own stuff (I could have claimed it as mine for the purpose of getting things done, but I still didn't understand what exactly I was doing and didn't want to be required to fix something I didn't understand when it broke).
First, the samples given here and elsewhere, while very helpful, included some extraneous details that contributed to my confusion.
Given the *simplest* requirement:
All of the examples included code like
ormy $IN = IO::File->new_tmpfile;
and then proceed to call the open3 with those filehandles.local *OUT; open OUT, ">output.log";
They aren't needed, at least for something this simple. Once I realized this I was able to get things working:
Any comments or improvements would be appreciated. I realize I need to add some checks for references and the like.sub callexternalpgm { my ( $cmd, $cmdargs, $rawdata, $processeddata, $err ) = @_; my ( $IN, $OUT, $ERR ); $ERR = gensym(); my $pid; eval{ $pid = open3( $IN, $OUT, $ERR, $cmd, @{ $cmdargs } ) }; return $@ if $@; print $IN $rawdata; close $IN; my $select = new IO::Select; $select->add( $OUT, $ERR ); while(my @ready = $select->can_read) { foreach my $fh (@ready) { my $data; my $length = sysread $fh, $data, 4096; if( ! defined $length || $length == 0 ) { $err .= "Error from child: $!\n" unless defined $length; $select->remove($fh); } else { if($fh == $OUT) { $processeddata .= $data; } elsif($fh == $ERR) { $err .= $data; } else { return undef; } } } } waitpid $pid, 0; # wait for it to die warn $err if $err; return 1; }
In reply to I got IPC::Open3 to work! by harleypig
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |