使用File::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个文件都具有相同的名称。 除了这只是奇怪的(并且你永远不希望你的代码很奇怪),我担心这可能会导致读取/写入同一个文件,以满足不同的请求。
答案 0 :(得分:3)
我查看了File::Temp
的来源。它用perl的简洁位替换了模板中的X:
$path =~ s/X(?=X*$end)/$CHARS[ int( rand( @CHARS ) ) ]/ge;
它使用perl的内置rand
,它只是一个传统的基于种子的随机数生成器。 rand
函数不具有加密安全性。它的种子也是“全球状态”,这可能导致分叉时出现问题,如下所述:
http://blogs.perl.org/users/brian_phillips/2010/06/when-rand-isnt-random.html
它的主旨是:如果你分叉两个perl解释器,并且原始解释器已经通过一次调用rand
播种,则两者都在fork
之后继承相同的种子,所以两者都将从该点生成相同的随机数序列。糟糕!因此,在调用srand
或其他任何调用tempfile
的内容之前,您可能需要在模块中调用rand
个。
也就是说,看起来File::Temp
需要很大的力气来检测和避免碰撞,但它会在某些时候放弃。以下警告隐藏在File::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.