【问题标题】:Die if anything is written to STDERR?如果向 STDERR 写入任何内容,会死吗?
【发布时间】:2013-12-12 18:59:25
【问题描述】:

如果向 STDERR 写入任何内容,我如何强制 Perl 脚本终止?

当这样的输出发生时,甚至在发生之前,应该立即执行这样的操作,以防止该输出......

【问题讨论】:

  • @sputnick - 不涉及系统命令...
  • 通过什么写入stderr? (即,您的意思是包括由您的进程启动的其他进程?您的 perl 代码调用的 C 库代码?perl 警告?显式打印到 stderr?)
  • @ysth - 任何东西,包括但不限于您提到的所有内容......
  • use warnings FATAL => 'all'?

标签: perl


【解决方案1】:

这似乎不是一个特别聪明的主意,但绑定的文件句柄应该可以工作。根据perltie 联机帮助页:

当 STDERR 绑定时,将调用其 PRINT 方法来发出警告和错误消息。此功能在调用期间暂时禁用,这意味着您可以在 PRINT 中使用 warn() 而无需启动递归循环。

所以像这样(改编自手册页示例)应该可以工作:

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.";

然后输出(退出代码为 255):

message to STDERR: this should be fatal. at fh.pl line 17.

【讨论】:

    【解决方案2】:

    无论 STDERR (fd 2) 是如何写入的,即使它是不使用 Perl 的 STDERR 变量的 C 扩展,这也是一种有效的方法。它甚至会杀死写入 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
    

    不适用于 Windows。如果添加 SIGPIPE 处理程序,则不起作用。

    【讨论】:

    • 有趣!如果我想在退出前添加一些功能,请问我需要如何修改您的代码?此外,它会与“模具处理程序”$SIG{__DIE__} = \&__die__; 一起使用吗?
    • 不,它没有死。它被操作系统杀死了。 $SIG{PIPE} 会抓住它。
    • 我怎样才能在你的代码被杀死之前添加一些功能(回调函数)?
    • $SIG{PIPE} 会抓住它。
    • 不同的问题有不同的答案。在最初的问题中,您要求程序结束。拥有 SIGPIPE 处理程序会阻止程序结束,这很糟糕。但是现在你想要做一些事情来响应事件而不是死亡。拥有一个 SIGPIPE 处理程序会阻止程序结束,这很好。
    猜你喜欢
    • 2011-05-21
    • 2014-07-12
    • 2019-04-25
    • 1970-01-01
    • 2016-08-08
    • 1970-01-01
    • 2019-03-16
    • 2012-11-18
    • 2016-03-29
    相关资源
    最近更新 更多