编写守护进程时,我想关闭STDIN,STDOUT和STDERR以获得“良好的守护程序行为”。但我很惊讶。后续打开文件需要与旧STDIN,STDOUT和STDERR相同的属性(因为它们的文件名被重新打开了?)
这是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中?
这似乎与How can I reinitialize Perl's STDIN/STDOUT/STDERR?类似,但是接受的解决方案是像我一样关闭STDIN,STDOUT和STDERR。
答案 0 :(得分:5)
这些是警告,而不是错误。我认为它们存在是因为如果你的程序随后分叉并执行了一个不同的程序,那么该程序将被大大混淆,它的标准输入流被打开以进行输出,并且它的标准输出和错误流被打开以供输入。
当你确定自己知道自己在做什么时,抑制警告是完全合法的。在这种情况下,您只需在no warnings 'io';
之前添加open
。
答案 1 :(得分:3)
现在,在点击提交后,我想到查看perldoc perldiag
并在那里列出警告文本。这导致我Perl bug #23838基本上说:“好吧,不要关闭这些句柄,而是将它们重新打开到'/ dev / null'而不是”。
此后,错误标记为已解决。
我不同意重新打开'/ dev / null'是正确的方法(tm),但现在我们冒险进入了意见,这对于stackoverflow来说是偏离主题的,所以我会将其标记为已回答。
对不起噪音。