0

我的环境是:Windows、MsSQL 和 PHP 5.4。

我的场景:我正在做一个小的 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 并且它也找不到源文件,当 rename 不能时。
  • 由于找不到文件,copy() 和 unlink() 也不起作用
  • 试过 clearstatcache()
  • sql备份完成后尝试sleep(10)

这些都没有帮助。我和谷歌似乎对下一步做什么或尝试没有想法。当然,我可以执行一些 shell_execing,但这并不能消除我对早期产品的担忧。

当我尝试连续多次运行该命令时,我才注意到这个问题。是否有 clearstatcache() 不会触及的文件名的某种缓存?它似乎与某种幽灵文件现象有关,其中 php 刷新文件系统内容等迟到了。

我将不胜感激有关下一步尝试的任何想法,如果您读到这里,谢谢:)。

4

3 回答 3

0

可能是缓存相关的,或者mysql进程还没有释放文件。mysql 会将文件转储到另一个临时文件中,首先将其移动到您的临时文件夹中。在移动文件时,其他进程可能无法访问它。

首先,当出现错误时,我会尝试使用glob()temp dir 中的所有文件。也许你注意到了,它还没有完成。

您是否也尝试过实施 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');
}
于 2014-03-07T15:55:06.827 回答
0

尝试

$source = "\\server01\temp\backups\file.bak";
$destination = "\\server02\storage\backups\file.bak";
$content = file_get_content($source);
file_put_contents($destination, $content);
于 2014-03-07T15:09:08.343 回答
0

您可以尝试调用系统的copy命令。当我不得不在两个 NFS 共享之间复制文件时,我曾经遇到过像你一样的问题(在 Linux 机器上)。它只是不时地失败,没有明显的原因。在我切换到cp(Windows 副本的模拟)之后,问题就消失了。

当然它并不完美,但它对我有用。

于 2014-03-07T14:52:09.097 回答