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

I'm trying to execute a command via system but I would like to throw away any data that that command sends to STDOUT.

The command looks like

$rc = system(@command);

The cookbook says I can do somethink like...
open(STDOUT,'>/dev/null') || die $!;
before the system command, and this works.

Also, can you show me how to do it using the OPP IO::File interface?
thanks.
But, I would like to restore STDOUT after the system command.
How do I do this?

Replies are listed 'Best First'.
Re: Redirecting STDOUT
by ctilmes (Vicar) on May 02, 2003 at 19:06 UTC
Re: Redirecting STDOUT
by chromatic (Archbishop) on May 02, 2003 at 19:10 UTC

    I don't use IO::File, but this is a good use of local:

    { local *STDOUT; open( STDOUT, '>/dev/null' ) or die "Cannot redirect STDOUT: $!\n" +; $rc = system( @command ); }
      I believe that won't work, based on some tests. Localizing *STDOUT breaks the magic that ensures that ensures that the STDOUT handle always has fd 1, and the fd is the only thing that matters when spawning a child. Something similar that should work is:
      { local *FOO; open FOO, ">&STDOUT"; # fileno(FOO) = dup(1) open STDOUT, ">/dev/null"; # dup2(open(), 1) system @command; open STDOUT, ">&FOO"; # dup2(fileno(FOO), 1) }

          -- Chip Salzenberg, Free-Floating Agent of Chaos

Re: Redirecting STDOUT
by Anonymous Monk on May 02, 2003 at 19:40 UTC
    Make a copy of STDOUT:
    open SAVOUT, ">&STDOUT"; # copy of STDOUT open STDOUT, ">/dev/null";
    Then to restore STDOUT later:
    open STDOUT, ">&SAVOUT"; close SAVOUT;
      That works great, but how would you do the same using IO::File?
      I was just wondering if it was even possible.
Re: Redirecting STDOUT
by chip (Curate) on May 02, 2003 at 19:30 UTC
    I recommend IPC::Run:

    use IPC::Run; run \@command, '>', '/dev/null';
    I think IPC::Run is one fricking cool module. Too bad it's a bit slow to load. Maybe that can be fixed....

        -- Chip Salzenberg, Free-Floating Agent of Chaos

      It's a very cool module indeed, but the interface is really nothing short of ugly in my opinion. I understand why it's trying to mimick the shell syntax, but since it is used from within Perl code, it requires a lot of quotes and commata all over the place to carry metacharacters and filenames, resulting in lots of line noise. I have some vague ideas for an interface that'd feel more natural for Perl code, but unfortunately none at all about writing robust guts for this kind of task.

      Makeshifts last the longest.

Redirecting STDOUT
by jonadab (Parson) on May 03, 2003 at 00:10 UTC

    Do you really need for Perl to be able to detect that its output is being thrown away (and thus not bother copying it) or do you just not want the output? How many times per minute does this need to run, and how many megabytes of data does it add up to that you're throwing away total? Because, if you just don't need the output, you can save yourself a good deal of messing around by just calling system in void context.

    do_stuff(); system($command, @args); do_more_stuff();

    In theory Perl _could_ detect that system is called in void context not as the last item in the block and so could optimise away copying the command's output. In practice I don't know whether it does or not, but this only matters if you have a significant performance or footprint issue due to the size of the output being large or the system call being repeated quite often. If not, do it and don't sweat it. Don't optimise things that don't need to be optimised; it makes your code that much longer and less clear for no good reason.


    {my$c;$ x=sub{++$c}}map{$ \.=$_->()}map{my$a=$_->[1]; sub{$a++ }}sort{_($a->[0 ])<=>_( $b->[0])}map{my@x=(& $x( ),$ _) ;\ @x} split //, "rPcr t lhuJnhea eretk.as o";print;sub _{ord(shift)*($=-++$^H)%(42-ord("\r"))};
      its a client server app
      we have an application (sqr) that can only run (licensing issues) on one machine. Currently we rsh commands over to that box. This has been ok for many years but now we have run up against resource issues with that box. Our unix sa says that there is a limit on the number or rsh sessions that it can handle. So , we decided to rewrite the process using a socket client forking-server set of programs. What I found out while doing this is that many programmers have left alot of debug 'show' commands in their sqr code. For debuging and testing of this new process it was necessary for me to be able to not have all the clutter of these 'debug' statments spewing into the stdout of the server (the parent process).
Re: Redirecting STDOUT
by draconis (Scribe) on May 03, 2003 at 17:04 UTC
    Since you are wanting to throw away the output of the command you could use qx().

    $output=qx(@command);

    now you have captured the output in $output and can do whatever you wish with it.