Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

How to hide system(); output.

by bcens (Novice)
on Jan 30, 2010 at 00:33 UTC ( [id://820437]=perlquestion: print w/replies, xml ) Need Help??

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

Hi Monks. First post here. Long time reader! I have several applications that I have developed using Perl on Windows. All of those apps from time to time need to call other programs for things like COM-API's and the likes.

Everything is OK except when I (example:)
$command = "do this, and do that"; system("$command");

The output of the called application is shown in the users browser! Not so much of a issue with some applications but some have output that shows paths, usernames and other data that I just do not want displayed.

How can I supress ALL output from system(); calls? Thanks in advance!

Replies are listed 'Best First'.
Re: How to hide system(); output.
by toolic (Bishop) on Jan 30, 2010 at 01:16 UTC
Re: How to hide system(); output.
by ikegami (Patriarch) on Jan 30, 2010 at 04:43 UTC

    A solution that doesn't involve calling the shell if you don't already:

    use IPC::Open3 qw( open3 ); { open(local *NUL, '>', 'NUL') or die; my $pid = open3('<&STDIN', '>&NUL', '>&NUL', $command); waitpid($pid, 0); }
Re: How to hide system(); output.
by graff (Chancellor) on Jan 30, 2010 at 01:21 UTC
    If you were using anything but a windows system, you could just form the command line like this:
    $command = "(do this && do that) >/dev/null 2>&1";
    Maybe the default "cmd.exe" (or whatever gets used on windows to run commands via the system() call) provides some equivalent sort of idiom, if you know how to look that up... (or maybe you can set things up so that your "do this, and do that" stuff gets run via a bash.exe shell, so you can at least redirect output to some file that you can then delete -- possibly after reading it to check for error conditions?)

    Apart from that, since the main problem is the fact that your perl script is running in an environment where all output to STDOUT goes to some browser client, what you have to do is to change the STDOUT file handle so that stuff written to that handle will end up somewhere else, like a scalar variable (read the output of perldoc -f open):

    close STDOUT; open STDOUT, '>', \$variable; system( $command ); close STDOUT; # you might want to check what got put into $variable... open STDOUT, '>-'; # reopen the real stdout
    UPDATE: the above snippet was not tested, and on testing it, it doesn't work as intended. See ikegami's reply to me.

      open STDOUT, '>', \$variable;

      That won't work. That Perl file handle doesn't have a system file handle associated with it, so the child can't see it. You could use

      $variable = `$command`;
        Oops. Thanks for pointing that out. (I should have tested before posting.)

        While we're at it (now that I have tried it out), there's another aspect of my snippet that didn't work as I expected: re-opening STDOUT that way does not seem to put things back the way they were:

        #!/usr/bin/perl warn "\n==normal case:\n"; print "running ls:\n"; system( "ls" ); close STDOUT; warn "\n==STDOUT closed:\n"; print "running ls a 2nd time\n"; system( "ls" ); open STDOUT, '>-'; warn "\n==STDOUT reopened:\n"; print "running ls a 3rd time\n"; system( "ls" );

        When I run that in at terminal shell, the only output I get on STDOUT comes from the "normal case", nothing shows up after the second and third "warn" messages (bummer).

        I had to read farther into the manual description of open to get it right:

        #!/usr/bin/perl warn "\n==normal case:\n"; print "running ls:\n"; system( "ls" ); open my $oldout, ">&STDOUT"; # "dup" the stdout filehandle close STDOUT; warn "\n==STDOUT closed:\n"; print "running ls a 2nd time\n"; system( "ls" ); open STDOUT, '>&', $oldout; # restore the dup'ed filehandle to STDOUT warn "\n==STDOUT reopened:\n"; print "running ls a 3rd time\n"; system( "ls" );
        (updated to add comments)

        That sort of thing could make a big difference in the OP's situation, where there might be other stuff to be written back to a browser after running a system call.

      Maybe the default "cmd.exe" (or whatever gets used on windows to run commands via the system() call) provides some equivalent sort of idiom, if you know how to look that up...

      The equivalent on Windows (at least my cmd.exe) would be:

      $command = "ipconfig >nul 2>1";

        Each suggestion worked equally. Thank you both for the fast help.
Re: How to hide system(); output.
by krikbugs (Novice) on Jan 30, 2010 at 08:07 UTC
    backticks !! $output = `$command`;
Re: How to hide system(); output.
by xiaoyafeng (Deacon) on Jan 31, 2010 at 14:18 UTC
    if other programs is used to call COM-API, how could you try to rewrite in Win32::OLE?




    I am trying to improve my English skills, if you see a mistake please feel free to reply or /msg me a correction

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://820437]
Approved by toolic
Front-paged by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (9)
As of 2024-03-28 23:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found