Perl File :: Temp,文件名不是随机的

时间:2013-07-10 08:08:15

标签: perl mod-perl temporary-files

使用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个文件都具有相同的名称。 除了这只是奇怪的(并且你永远不希望你的代码很奇怪),我担心这可能会导致读取/写入同一个文件,以满足不同的请求。

1 个答案:

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