Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Die if anything is written to STDERR?

Tags:

perl

How can I force Perl script to die if anything is written to STDERR ?

Such action should be done instantly, when such output happen, or even before, to prevent that output...

like image 429
Ωmega Avatar asked Dec 12 '13 18:12

Ωmega


People also ask

What does stderr mean?

Stderr, also known as standard error, is the default file descriptor where a process can write error messages. In Unix-like operating systems, such as Linux, macOS X, and BSD, stderr is defined by the POSIX standard. Its default file descriptor number is 2.

Should I print to stderr?

It is good practice to redirect all error messages to stderr , while directing regular output to stdout . It is beneficial to do this because anything written to stderr is not buffered, i.e., it is immediately written to the screen so that the user can be warned immediately.

How do I send output to stderr?

The regular output is sent to Standard Out (STDOUT) and the error messages are sent to Standard Error (STDERR). When you redirect console output using the > symbol, you are only redirecting STDOUT. In order to redirect STDERR, you have to specify 2> for the redirection symbol.

What do you use stderr for?

Stderr is the standard error message that is used to print the output on the screen or windows terminal. Stderr is used to print the error on the output screen or window terminal. Stderr is also one of the command output as stdout, which is logged anywhere by default.


2 Answers

This doesn't seem like an especially smart idea, but a tied filehandle should work. According to the perltie manpage:

When STDERR is tied, its PRINT method will be called to issue warnings and error messages. This feature is temporarily disabled during the call, which means you can use warn() inside PRINT without starting a recursive loop.

So something like this (adapted from the manpage example) ought to work:

package FatalHandle;

use strict;
use warnings;

sub TIEHANDLE {  my $i; bless \$i, shift }

sub PRINT { 
    my $r = shift; 
    die "message to STDERR: ", @_;
}

package main;

tie *STDERR, "FatalHandle";

warn "this should be fatal.";

print "Should never get here.";

And that outputs (with exit code 255):

message to STDERR: this should be fatal. at fh.pl line 17.
like image 175
friedo Avatar answered Sep 25 '22 20:09

friedo


Here's a method that works no matter how STDERR (fd 2) is written to, even if it's a C extension that doesn't use Perl's STDERR variable to do so. It will even kill child processes that write to STDERR!

{
   pipe(my $r, my $w)
      or die("Can't create pipe: $!\n");
   open(STDERR, '>&', $w)
      or die("Can't dup pipe: $!\n");
   close($r);
}

print "abc\n";
print "def\n";
print STDERR "xxx\n";
print "ghi\n";
print "jkl\n";

$ perl a.pl
abc
def

$ echo $?
141

Doesn't work on Windows. Doesn't work if you add a SIGPIPE handler.

like image 21
ikegami Avatar answered Sep 24 '22 20:09

ikegami