mpapec
mpapec

Reputation: 50667

Silencing STDERR and warnings

How does warn 4 differ from print STDERR 4?

perl -e 'local *STDERR; warn 4'

(output still goes to STDERR)

perl -e 'local *STDERR; print STDERR 4'

(no output here)

Upvotes: 4

Views: 469

Answers (3)

ikegami
ikegami

Reputation: 386646

  • warn triggers $SIG{__WARN__}.
  • warn doesn't use $\ or $,.
  • And warn apparently uses the file handle in the original STDERR, as you've demonstrated[1].

  1. Not quite. Your code could also demonstrate that warn uses fd 2 directly, but that's disproven by

    close(STDOUT);
    close(STDERR);
    open(STDERR, '>file');
    warn(fileno(STDERR)."abc");  # 1abc
    

Upvotes: 6

Vassilii Khachaturov
Vassilii Khachaturov

Reputation: 150

local here only says that the typeglob STDERR is local from this point on, it doesn't change anything with STDERR handle already seen by sig warn default handler by the time you enter this block. You need to reopen the handle to something else if you want to really silence STDERR.

If you want to silence it locally and then restore, here's how to do it, if you really must insist to resort to low-level globs and handles:

#!/usr/bin/perl -w
sub f() {
    local *STDERR;
    open STDERR, '>/dev/null';
    warn 4;
}
warn 3;
f();
warn 5;

Upvotes: 2

devnull
devnull

Reputation: 123648

You haven't silenced the STDERR handle yet. In order to really silence it, you need to say:

perl -e 'local *STDERR; open(STDERR, ">/dev/null") or die $!; warn 4'

perldoc perlvar tells:

As the 'IGNORE' hook is not supported by __WARN__, you can disable warnings using the empty subroutine:

 local $SIG{__WARN__} = sub {};

Upvotes: 4

Related Questions