问题出在这里:我有一个守护进程,它从客户端获取请求,由于请求而执行一个函数(来自某个模块),并向客户端返回一个答案.在fork()之后我关闭了STDIN,STDOUT和STDERR.一个功能是检查dmesg.为此,我通过open(DMESG,"/ bin/dmesg |")获得dmesg输出.读完之后我没有关闭这个fh,因为我认为它会在函数完成后自动关闭.但这不会发生,每次调用dmesg我都会得到一个僵尸.
关于如何重新初始化Perl的STDIN/STDOUT/STDERR?我发现"关闭STDOUT而不是重新打开的问题是,如果你打开其他文件,它们可能会得到fd 0,1或2 - 阻止你将来重新打开STDOUT." 作者:jmanning2k我认为它与它有关但我并没有真正得到它.我希望有人可以向我解释.
我知道我可以避免这个问题,例如通过qx()调用dmesg; 或者只是关闭fh,但我想了解僵尸的来源.
在编写守护进程时,我想关闭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 …Run Code Online (Sandbox Code Playgroud)