Hello,
Yes, I'm using IPC::Open3.
I wrote such code to be able to run different commands, pass them need data into STDIN, and store their STDOUT and STDERR. and exam various exit codes:
sub _run {
my $cmd = shift; # CMD to execute as plain string
my $input = shift; # CMD STDIN data
$cmd_timeout = 1000; # Default commant exucution timeuot
my $pid = open3(*CMD_IN, *CMD_OUT, *CMD_ERR, $cmd);
my($rc, $exit_value, $signal_num, $dumped_core, $waitpid);
$exit_value = -1;
$signal_num = 0;
print CMD_IN $input if( defined($input) );
close(CMD_IN);
if( $pid > 0 ) {
#wait before finished
my $patience = time() + $twait;
my ($child);
$? = 0;
# Wait up to the timeout
# And clean off the zombie
do {
$child = waitpid(-1, WNOHANG);
$rc = $?;
$exit_value = WEXITSTATUS($rc);
$signal_num = WIFSIGNALED($rc);
select(undef, undef, undef, 0.1);
} while time() < $patience && $child != $pid;
if( $exit_value == -1 ) {
#timeout - kill task and set error flag.
warn "Killing $pid because off wait timeout\n";
kill("KILL", $pid);
}
}
# get zombies
while(waitpid(-1, WNOHANG)>0) {
;
}
my $selector = IO::Select->new();
# collect STDOUT and STDERR
$selector->add(*CMD_ERR, *CMD_OUT);
my @stdout = ();
my @stderr = ();
while(my @ready = $selector->can_read()){
foreach my $fh (@ready){
if(fileno($fh) == fileno(CMD_ERR)){
push(@stderr, <CMD_ERR>);
}
else{
push(@stdout, <CMD_OUT>);
}
$selector->remove($fh) if eof($fh)
}
}
close(CMD_OUT);
close(CMD_ERR);
if( $pid <= 0 || $exit_value != 0 ){
warn "\nCMD: $cmd\nSTDERR: @stderr\nSTDOUT: @stdout\nSTATUS: $rc\nEXITSTATUS: $exit_value\nSIGNALED: $signal_num\nPID: $pid\n";
}
return($exit_value, \@stdout, \@stderr);
}
The code failes to execute the command like:
rpm -q quota
Am I doing something wrong?
Thanks.