note
Celada
<p>Is it enough to merge the stdout together with the stderr into one stream? If so then you could do</p>
<code>
$output = `$cmd 2>&1`
</code>
It sounds like you want to capture the stdout and stderr into seperate variables though. You will need this:
<code>
use strict;
use IO::Select;
use POSIX;
pipe(STDOUT_READ, STDOUT_WRITE) || die;
pipe(STDERR_READ, STDERR_WRITE) || die;
my $pid = fork();
die unless (defined($pid));
if ($pid == 0) {
close STDOUT_READ;
close STDERR_READ;
open(STDOUT, ">&STDOUT_WRITE");
open(STDERR, ">&STDERR_WRITE");
close STDOUT_WRITE;
close STDERR_WRITE;
exec $cmd;
POSIX::_exit(1);
}
my $stdout_collected = "";
my $stderr_collected = "";
close STDOUT_WRITE;
close STDERR_WRITE;
my $sel = IO::Select->new();
$sel->add(\*STDOUT_READ);
$sel->add(\*STDERR_READ);
my $remaining = 2;
while ($remaining > 0) {
my @ready = $sel->can_read();
for my $r (@ready) {
my $got;
if (sysread($r, $got, 1024) == 0) {
close $r;
$remaining--;
}
($r == \*STDOUT_READ) ?
$stdout_collected :
$stderr_collected .= $got;
}
}
undef $sel;
waitpid $pid, 0;
# stdout is collected in $stdout_collected
# stderr is collected in $stderr_collected
</code>
<p><b>Update:</b> Changed <c>read</c> to <c>sysread</c></p>
520082
520082