Can you temporarily turn off STDERR?

(Berger, Daniel) #1

This comes up often enough that I wonder if allowing IO#reopen to take a
block would be a good idea:

$stderr.reopen('/dev/null') do
   # Code here redirects to /dev/null
end

# Code outside the block behaves normally

I thought this idea had been brought up before, and that there was some
downside to this, but I can't find any references to it now.

Thoughts?

- Dan

This communication is the property of Qwest and may contain confidential or
privileged information. Unauthorized use of this communication is strictly
prohibited and may be unlawful. If you have received this communication
in error, please immediately notify the sender by reply e-mail and destroy
all copies of the communication and any attachments.

···

-----Original Message-----
From: ara.t.howard@noaa.gov [mailto:ara.t.howard@noaa.gov]
Sent: Friday, August 25, 2006 1:46 PM
To: ruby-talk ML
Subject: Re: Can you temporarily turn off STDERR ??

On Sat, 26 Aug 2006, bradjpeek wrote:

> Inside a ruby script I want to:
>
> 1) redirect STDERR to /dev/null
> 2) Issue a system call (e.g. system(tar xf tarfile file) )
> 3) revert to normal STDERR output
>
> I have a script that issues 3-4 system calls that are returning the
> following message to STDERR:
>
> warning: Insecure world writable dir /opt, mode 040777
>
> I'd like to suppress these messages (Let's assume that I
can't change
> the permissions on /opt).
>
> An example of one of the lines that is throwing the error is:
>
> x = `tar tf mytar.tar` # envoke the unix tar command
> print x

the warning is from ruby.

   $VERBOSE = nil

will shut it up

if you want it shut up only sometimes do

   def quiet
     v = $VERBOSE
     yield
   ensure
     $VERBOSE = v
   end

then

   x = quietly{ `tar tf mytar.tar` }
   print x

> Any suggestions?

if you really want fine control over stdin/stdout/stderr of
executed commands check out my session and open4 libs

   http://codeforpeople.com/lib/ruby/session/session-2.4.0/README
   http://codeforpeople.com/lib/ruby/open4/open4-0.5.1/README

in particular the Open4::spawn command. both are available as

(Aredridel) #2

This comes up often enough that I wonder if allowing IO#reopen to take a
block would be a good idea:

$stderr.reopen('/dev/null') do
   # Code here redirects to /dev/null
end

# Code outside the block behaves normally

I thought this idea had been brought up before, and that there was some
downside to this, but I can't find any references to it now.

Thoughts?

Can't handle threading sanely, for one.

(Stephen Veit) #3

How about this?

#!/usr/bin/env ruby

# reopen_with_block.rb

class IO

  alias_method :_orig_reopen, :reopen

  def reopen(*args)
    if block_given?
      is_path = args.length == 2
      path_or_io, mode_str = args
      old_io = clone
      path_or_io = File.open(path_or_io, mode_str || "w") if is_path
      _orig_reopen(path_or_io)
      begin
        yield
      ensure
        _orig_reopen(old_io)
        path_or_io.close if is_path
      end
    else
      _orig_reopen(*args)
    end
  end

end

if $0 == __FILE__
  $stderr.reopen('error_log', 'w') do
    $stderr.puts "Stuff on error"
    puts "normal stuff"
  end

  File.open('error_log_2', "w") do |file|
    $stderr.reopen(file) do
      $stderr.puts "Stuff on error 2"
      puts "normal stuff 2"
    end
  end

  $stderr.reopen('/dev/null') do
    $stderr.puts "Stuff on error 3"
    puts "normal stuff 3"
  end

  # Make sure old way works
  old_stderr = $stderr.clone
  File.open('error_log_4', 'w') do |log_file|
    $stderr.reopen(log_file)
    begin
      $stderr.puts "Stuff on error 4"
      puts "normal stuff 4"
    ensure
      $stderr.reopen(old_stderr)
    end
  end

  begin
    $stderr.reopen('error_log_5', 'w') do
      $stderr.puts "Stuff on error 5"
      puts "normal stuff 5"
      raise "This message courtesy of raise"
    end
  rescue => e
    puts e
  end

end

···

On 8/25/06, Berger, Daniel <Daniel.Berger@qwest.com> wrote:

This comes up often enough that I wonder if allowing IO#reopen to take a
block would be a good idea:

$stderr.reopen('/dev/null') do
   # Code here redirects to /dev/null
end

# Code outside the block behaves normally

I thought this idea had been brought up before, and that there was some
downside to this, but I can't find any references to it now.

Thoughts?

- Dan