2014-03-07 30 views
0

我的環境是:Windows,MsSQL和PHP 5.4。PHP rename()不能總是在Windows環境中找到源文件(代碼2)

我的場景: 我正在做一個小的shell腳本,它可以從我想要的數據庫創建一個完整備份到一個臨時文件夾,然後將它移動到一個新位置。

備份正常,文件創建到我的臨時文件夾。然後我將它重命名爲第二個文件夾,有時它會正常,有時它找不到源文件。

當然在這一點上,我知道我可以跳過所有的臨時位置,但沒有找到該文件的實際問題困擾我。爲什麼它是如此隨機,並且可能會影響我在此之前編寫的其他文件功能......另外,我需要能夠控制文件如何以及何時移動到目的地。

的基本代碼很簡單,因爲它應該是(雖然這是我的實際代碼的簡化版本,因爲我懷疑任何人有興趣在我的錯誤處理/記錄條件):

$query = "use test; backup database test to disk '//server01/temp/backups/file.bak', COMPRESSION;"; 

if($SQLClass->query($query)) { 

    $source="////server01//temp//backups//file.bak"; 
    $destination="////server02//storage//backups//file.bak"; 

    if(!rename($source , $destination)) { 
     //handleError is just a class function of mine that logs and outputs errors. 
     $this->handleError("Moving {$source} to {$destination} failed."); 
    } 
} 
else { 
    die('backup failed'); 
} 

我已嘗試的是:

  • 我在它之前添加了一個file_exists,它無法找到源文件,當重命名不能。
  • 由於文件無法找到,在SQL備份副本後()和unlink()將不工作,要麼
  • 嘗試clearstatcache()函數
  • 嘗試睡眠(10)完成

無這些根本沒有幫助。我和谷歌似乎沒有想法做什麼或嘗試下一步。當然,我可以使用一些shell_execing,但這並不能消除我對早期產品的擔憂。

我只在連續多次運行命令時才注意到這個問題。有沒有某種clearstatcache()不會觸及的文件名緩存?它似乎與某種幽靈文件現象有關,其中php遲到刷新文件系統內容等。

我會感激任何想法接下來要嘗試什麼,如果你讀到這遠,謝謝你:)。

+0

您是否檢查過fil的權限e在你當前用戶的服務器中? – Javad

+0

您是否曾嘗試將重命名調用放在一個可以睡眠一段時間的循環中,並在調用'handleError'之前重試3-5次?有時這有助於偶爾超時的文件操作。 – Dan

+0

是的,我有和權利是好的。這也是我早期的想法,但結果是該文件有時無法找到。我沒有嘗試循環它,但我確實嘗試了10秒鐘睡眠。我會嘗試一下,看看它是否工作,也許調用相同的函數兩次重置。 – MacRedrum

回答

0

您可以嘗試撥打系統的copy命令。 當我不得不在兩個NFS共享文件之間複製文件時,我曾經遇到過像您的問題(在Linux機器上)。它不時失敗,沒有明顯的原因。我切換到cp(Windows副本的模擬)問題已經消失。

當然,這不是完美的,但它對我有效。

+0

這可能是唯一的解決方案。我一直對php的文件功能有點警惕。但是,既然我以前從來沒有遇到過任何與他們相處的問題,我已經使用過它們了。 – MacRedrum

+1

我寫了一個小file_move($ source,$ dest)函數。即使這樣看起來有時太快,但至少它比迄今爲止的php文件功能更穩定。 – MacRedrum

0

嘗試

$source = "\\server01\temp\backups\file.bak"; 
$destination = "\\server02\storage\backups\file.bak"; 
$content = file_get_content($source); 
file_put_contents($destination, $content); 
+0

剛剛嘗試過這一點,它隨機得到相同類型的隨機錯誤:「未能打開流:沒有這樣的文件或目錄」。就像rename()一樣,這個過程也有時候會起作用。 – MacRedrum

+0

您是否知道在從$ source讀取或保存到$ destination時是否出現此問題? – Javad

+0

是的來源。完整的錯誤:「錯誤:file_get_contents(//server01/temp/backups/file.bak):無法打開流:沒有這樣的文件或目錄」。此外,我有一些功能,確保目標文件夾存在(當然,第一次運行後,它總是也一樣) – MacRedrum

0

這可能是緩存相關,或者MySQL的進程尚未發佈的文件。 mysql會將該文件轉儲爲另一個臨時文件,首先將其移至您的臨時文件夾。 當文件被移動時,其他進程可能無法訪問該文件。

首先,我會嘗試​​3210所有文件在臨時目錄中,當出現錯誤。也許你注意到,它還沒有完成。

還有你試圖實施10次重試迭代,有一些延遲?

$notMoved = 0; 
while($notMoved < 10){ 
    $source="////server01//temp//backups//file.bak"; 
    $destination="////server02//storage//backups//file.bak"; 

    if(!rename($source , $destination)) { 
     //handleError is just a class function of mine that logs and outputs errors. 
     if ($notMoved++ < 10){ 
      sleep(20); 
     } else { 
      $this->handleError("Moving {$source} to {$destination} failed."); 
      break; 
     } 
    }else{ 
     break; 
    } 
} 

要繞過這個問題:

  • 不要轉儲和移動然後
  • 移動傾倒:-)

(OFC您的備份存儲將是一個落後呢。 )

$source="////server01//temp//backups//file.bak"; 
    $destination="////server02//storage//backups//file.bak"; 

    if(!rename($source , $destination)) { 
     //handleError is just a class function of mine that logs and outputs errors. 
     $this->handleError("Moving {$source} to {$destination} failed."); 
    } 

$query = "use test; backup database test to disk '//server01/temp/backups/file.bak', COMPRESSION;"; 

if($SQLClass->query($query)) { 
    //done :-) 
} 
else { 
    die('backup failed'); 
} 
+0

好吧,我試了10次循環,每次睡5秒。結果是可疑的。有時需要幾圈來移動文件。有時它會經歷所有10次迭代。把這樣的東西放到生產中是可怕的:)。 – MacRedrum

+0

@MacRedrum轉儲有多大?根據服務器負載和大小的不同,可能需要幾秒到臨時文件被複制到那裏。如果第一次移動是異步的,你的第二次移動嘗試將遇到問題。 – dognose

+0

目前大概有8個左右。它需要幾分之一秒。根據SQL服務器,它處理約50mb/s的備份。這就是爲什麼甚至在睡了50秒後仍然沒有找到它的原因。 – MacRedrum

相關問題