Perl文件::Temp,文件名不是随机的
我在使用Perl文件::Temp,文件名不是随机的,perl,mod-perl,temporary-files,Perl,Mod Perl,Temporary Files,我在使用文件::Temp时遇到了一个奇怪的问题: 我在Linux上Apache的mod_perl下运行我的perl脚本,Apache使用worker mpm运行 my ($fh_error, $error) = tempfile("error_XXXXXXXXXXXXXXXX",DIR => "/home/tmp", UNLINK => 1); my ($fh_src, $src) = tempfile("src_XXXXXXXXXXXXXXXX",DIR =>
文件::Temp时遇到了一个奇怪的问题:
我在Linux上Apache的mod_perl下运行我的perl脚本,Apache使用worker mpm运行
my ($fh_error, $error)
= tempfile("error_XXXXXXXXXXXXXXXX",DIR => "/home/tmp", UNLINK => 1);
my ($fh_src, $src)
= tempfile("src_XXXXXXXXXXXXXXXX",DIR => "/home/tmp", UNLINK => 1, SUFFIX => ".html");
my ($fh_dst, $dst)
= tempfile("dst_XXXXXXXXXXXXXXXX",DIR => "/home/tmp", UNLINK => 1, SUFFIX => ".html");
大多数时候,一切似乎都很好,但有时我会收到一些不好的文件名。
我得到的不是真正的随机文件名,而是所有模板长度的相同字母
比如说
error_AAAAAAAAAAAAAAAA
src_AAAAAAAAAAAAAAAA
dst_AAAAAAAAAAAAAAAA
所有3个文件都具有相同的名称。
除了这是奇怪的(而且你永远不希望你的代码是奇怪的)之外,我担心这可能会导致针对不同的请求读/写同一个文件 我查看了文件::Temp
的源代码。它用以下简洁的perl替换模板中的Xs:
$path =~ s/X(?=X*$end)/$CHARS[ int( rand( @CHARS ) ) ]/ge;
它使用perl内置的rand
,它只是一个传统的基于种子的随机数生成器。该rand
函数不是加密安全的。其种子也是“全局状态”,这可能导致分叉时出现问题,如下所述:
它的jist是:如果您分叉两个perl解释器,并且原始解释器已经通过一个对rand
的调用进行了种子设定,那么这两个解释器都会在分叉之后继承相同的种子,因此这两个解释器都将从该点生成相同的随机数序列。哎呀。因此,在调用tempfile
或调用rand
的任何其他内容之前,您可能需要调用模块中的srand
一个
这就是说,似乎File::Temp
在检测和避免冲突方面付出了巨大的努力,但在某个时候它会放弃。以下警告隐藏在文件::Temp
文档中:
If you are forking many processes in parallel that are all creating
temporary files, you may need to reset the random number seed using
srand(EXPR) in each child else all the children will attempt to walk
through the same set of random file names and may well cause themselves
to give up if they exceed the number of retry attempts.
猜测:也许你的熵用完了?你有没有在系统上运行munin(或类似的东西),你在“可用熵”图中看到了可疑的东西?该死的,我甚至没有想到,现在它有点低100-200是的,但即使熵为零,/dev/uradom
仍应该继续给出良好的伪随机数。它们的加密性不强(即,对于N个连续的随机数,理论上你可以计算出N+1的更好概率,对于足够大的N)。我自己做了一些挖掘,也发现了这个问题,我还发现了一个建议,将PerlChildInitHandler sub{srand}
添加到apache conf中,但它似乎不起作用