Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses

Re: capturing command output

by eyepopslikeamosquito (Chancellor)
on Jan 26, 2012 at 08:32 UTC ( #950040=note: print w/replies, xml ) Need Help??

in reply to capturing command output

We tend to avoid the Windows shell in Perl scripts that run external commands in customer environments over which we have no control. Some years ago we got burnt because some of our customers use a misfeature of Windows cmd.exe, namely that without the /d option, cmd.exe executes stuff from one of the following Registry values:

HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\AutoRun HKEY_CURRENT_USER\Software\Microsoft\Command Processor\AutoRun
before running your command. In one case, I remember there was a "cd" command in the customer autorun Registry which caused one of our Perl scripts to malfunction. We worked around it by replacing `some command 2>&1` with `cmd /d/c "some command" 2>&1`. An alternative workaround is to manipulate STDOUT and STDERR from perl, while taking care to call the Perl system function in such a way that the shell is not invoked.

To clarify, the two approaches are illustrated by the following two example programs:

use strict; use warnings; my $cmd = 'perl -le "print qq{to stdout};print STDERR qq{to stde +rr};exit 42"'; my $cmdhack = qq{cmd /d/c $cmd 2>&1}; # works # my $cmdhack = qq{cmd /d/c "$cmd" 2>&1}; # also works (despite bizar +re quoting) print "run:$cmdhack:\n"; my $out = `$cmdhack`; my $rc = $? >> 8; print "rc=$rc, stdout/stderr of command follows:\n"; print $out;


use strict; use warnings; my $outfile = 'ff.tmp'; my $exe = $^X; my @args = ( 'perl', '-le', 'print qq{to stdout};print STDERR qq{to + stderr};exit 42' ); print "run exe:$exe:args:@args:\n"; print STDERR "here we go to stderr\n"; open(SAVOUT, ">&STDOUT") or die "error: save original STDOUT: $!"; open(SAVERR, ">&STDERR") or die "error: save original STDERR: $!"; open(STDOUT, '>', $outfile) or die "error: create '$outfile': $!"; open(STDERR, '>&STDOUT') or die "error: redirect '$outfile': $!"; system { $exe } @args; my $rc = $? >> 8; open(STDOUT, ">&SAVOUT") or die "error: restore STDOUT: $!"; open(STDERR, ">&SAVERR") or die "error: restore STDERR: $!"; close(SAVERR) or die "error: close SAVERR: $!"; close(SAVOUT) or die "error: close SAVOUT: $!"; print "rc=$rc\n"; print STDERR "rc=$rc to STDERR\n";
Improvements welcome.

Update: tidied up and clarified the example code.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://950040]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (3)
As of 2018-03-24 08:22 GMT
Find Nodes?
    Voting Booth?
    When I think of a mole I think of:

    Results (297 votes). Check out past polls.