当关闭STDIN、STDOUT和STDERR时,是否存在Perl漏洞?

4
当编写守护进程时,我希望关闭标准输入、标准输出和标准错误以实现“良好的守护进程行为”。但是我感到惊讶。后续打开文件需要与旧的标准输入、标准输出和标准错误具有相同的属性(因为它们的文件描述符被重新打开了?)
以下是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;

现在我来运行它:

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

我原本期望没有警告,且$? == 0。这个问题是在我的代码中还是在perl中?这可能与此问题相似:如何重新初始化Perl的STDIN/STDOUT/STDERR?,但那里的解决方案是关闭STDIN、STDOUT和STDERR,就像我所做的一样。
2个回答

5
现在,提交后我想查看perldoc perldiag,并在那里列出警告文本。这让我想到了Perl bug #23838,基本上是说:“好吧,不要关闭这些句柄,改为重新打开它们到'/dev/null'。”之后该错误被标记为已解决。
我不同意重新打开到“/dev/null”是正确的方法(商标),但现在我们涉及观点,这与stackoverflow的主题无关,因此我将将其标记为已回答。
对于噪音问题我表示抱歉。

5

这些是警告消息而不是错误。我猜测它们的存在是因为如果你的程序随后分叉并执行了另一个程序,那个程序会非常困惑,因为它的标准输入流被打开用于输出,而它的标准输出和错误流则被打开用于输入。

当你确信自己知道自己在做什么时,压制警告是完全合法的。在这种情况下,你只需要在你的open之前添加 no warnings 'io';


我理解。孩子们看到 STDIN 被打开写入会感到困惑。谢谢。 - Peter V. Mørch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接