当STDIN,STDOUT和STDERR关闭时perl bug?

Pet*_*rch 3 perl

在编写守护进程时,我想关闭STDIN,STDOUT和STDERR以获得"良好的守护进程行为".但我很惊讶.后续打开文件需要与旧STDIN,STDOUT和STDERR相同的属性(因为它们的fileno-s被重新打开了?)

这是warn.pl:

use warnings;

my $nrWarnings = 0;
$SIG{__WARN__} = sub {
    no warnings;
    $nrWarnings++;
    open my $log, '>>', '/tmp/log.txt'
        or die;
    printf $log "%d: %s", $nrWarnings, @_;
    close $log;
};

close STDOUT;
close STDERR;
close STDIN;

open my $o, '>', '/tmp/foobar.txt'
    or die;
open my $i, '<', '/etc/passwd'
    or die;
open my $i2, '<', '/etc/passwd'
    or die;
open my $i3, '<', '/etc/passwd'
    or die;

exit $nrWarnings;
Run Code Online (Sandbox Code Playgroud)

在这里我运行它:

> rm -f /tmp/log.txt ; perl warn.pl; echo $? ; cat /tmp/log.txt 
3
1: Filehandle STDIN reopened as $o only for output at warn.pl line 20.
2: Filehandle STDOUT reopened as $i only for input at warn.pl line 22.
3: Filehandle STDERR reopened as $i2 only for input at warn.pl line 24.
Run Code Online (Sandbox Code Playgroud)

我期待没有警告和$?== 0.这个错误在哪里?在我的代码或perl中?

这可能类似于如何重新初始化Perl的STDIN/STDOUT/STDERR?,但是接受的解决方案是像我一样关闭STDIN,STDOUT和STDERR.

Pet*_*rch 5

现在,点击提交后,我想查看一下perldoc perldiag,警告文本就列在那里。这导致我发现Perl bug #23838,它基本上指出:“好吧,不要关闭这些句柄,而是将它们重新打开到 '/dev/null'”。

此后该错误将被标记为已解决。

我不同意重新打开“/dev/null”是正确的方法(tm),但现在我们冒险发表意见,这对于 stackoverflow 来说是题外话,所以我将其标记为已回答。

抱歉产生噪音。


Sea*_*ean 5

这些是警告,而不是错误.我认为它们存在是因为如果你的程序随后分叉并执行了一个不同的程序,那么该程序将被大大混淆,它的标准输入流被打开输出,其标准输出和错误流被打开输入.

当你确定你知道你在做什么时,抑制警告是完全合法的.在这种情况下,您只需no warnings 'io';在您的opens 之前添加.