1

我有一个奇怪的问题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 个文件都具有相同的名称。除了这很奇怪(而且你永远不希望你的代码很奇怪)之外,我担心这可能会导致读取/写入同一个文件以针对不同的请求。

4

1 回答 1

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

它的要点是:如果你 fork 两个 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.
于 2013-07-10T13:02:47.497 回答