2013-07-10 15 views
1

我有使用File::Temp一個奇怪的問題:的Perl文件::溫度,文件名不是隨機

我下的Linux上的Apache的mod_perl運行我的perl腳本,Apache的與工人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

一個猜測:也許你用盡了熵?你有沒有在系統上運行的munin(或類似的東西),並且你在「可用熵」圖中看到有可疑的東西嗎? –

+0

該死的連想都沒有想到,現在有點低了100-200 –

+0

是的,但即使是零熵,'/ dev/urandom'仍應該繼續給出好的僞隨機數。它們不會是密碼強大的(即使用N個連續的隨機數,理論上N + 1可能會更好,N足夠大)。 –

回答

3

我看了一下File::Temp的來源。它取代X們在模板用Perl的這種簡潔位:

$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

它的JIST是:如果你叉2個Perl解釋,和原來的解釋已經播種通過一次調用rand,兩者都會在fork之後繼承相同的種子,因此兩者都將從該點生成相同的隨機數字序列。糟糕!因此,在致電tempfile或其他調用rand之前,您可能需要在模塊中調用srand

也就是說,看起來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. 
+0

我做了一些自己挖掘並發現了這個問題,我也發現了一個建議,在Apache conf中添加'PerlChildInitHandler sub {srand}',但它似乎沒有工作 –