http://www.perlmonks.org?node_id=999397

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

Hi, I'm trying to get the stdout and stderr from a process executed from my perl script in the following way
use IO::CaptureOutput qw/capture/; $cmd = "xcopy /Y /S /E /I /F /R /K $source $dest"; capture { system $cmd } \$stdout, \$stderr; print "Output is : "."\n"."$stdout\n"; print "Error is : "."\n"."$stderr\n"; print "Exit code is : "."\n"."$?\n";
Problem is that this works fine exactly the way it is. I'm trying it in a windows xp professional machine with ActivePerl. But when I'm kicking off the command(xcopy, etc.) from a sub which is called from another sub, which in turn is called from another sub, $stdout comes up as an empty string. I'm echoing the values from the sub where the process is kicked off to get around issues related to scope of variables. I'm baffled by this. Does anybody know the answer to this weird behaviour. Will really appreciate it.

Replies are listed 'Best First'.
Re: get stdout stderr
by Tanktalus (Canon) on Oct 16, 2012 at 22:55 UTC

    I used to use IPC::Open3 for this type of thing. Now I use AnyEvent::Util::run_cmd:

    use AnyEvent; use AnyEvent::Util; use File::Spec; my ($stdout, $stderr) = ('', ''); # I think these need to be empty str +ings, not undefs my $pid; my $cv = AnyEvent::Util::run_cmd [ qw(xcopy /Y /S /E /I /F /R /K), $so +urce, $dest ], '<' => File::Spec->devnull(), '>' => \$stdout, '2>' => \$stderr, '$$' => \$pid, # this line is optional, you may not need it. ; my $rc = $cv->recv();
    (You can even run more than one of these at a time if you want, with a little extra code.)

Re: get stdout stderr
by kennethk (Abbot) on Oct 16, 2012 at 20:20 UTC
    I don't know if this is directly related to your issue and I've never worked with IO::CaptureOutput, but I've had difficulty shelling out in the past while capturing output to scalars. Detailed in STDOUT redirects and IPC::Open3, essentially the fileno of my output handles no longer corresponded to 0,1 and 2, and so the linking was lost on system call. The only solution I've found, assuming this is your issue, is rolling my own system call wrapper with pipe and fork, like in Re: How to capture child process output and divert to log4perl. In some cases, depending on some particulars, I've had to explicitly open unused filehandles to hold onto the right filenos until I needed them -- the system doles out filenos by the lowest one available.

    Or all this could be off base for your case.


    #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.