4

考虑这段代码:

public static function removeDir($src)
{
    if (is_dir($src)) {
        $dir = @opendir($src);
        if ($dir === false)
            return;
        while(($file = readdir($dir)) !== false) {
            if ($file != '.' && $file != '..') {
                $path = $src . DIRECTORY_SEPARATOR . $file;
                if (is_dir($path)) {
                    self::removeDir($path);
                } else {
                    @unlink($path);
                }
            }
        }
        closedir($dir);
        @rmdir($src);
    }
}

这将删除一个目录。但是,如果 unlink 失败或 opendir 在任何子目录上失败,则该目录将保留一些内容。

我想要删除所有内容,或者不删除任何内容。我正在考虑在删除之前复制目录,如果有任何失败,请恢复副本。但也许有更好的方法 - 比如锁定文件或类似的东西?

4

2 回答 2

1

我一般会确认评论:

“复制它,删除它,如果删除则复制回来,否则会导致删除消息失败......” – We0

但是,让我们考虑一些侧面:

尝试实现事务保存文件删除表明您希望允许对同一组文件进行竞争文件锁定。事务处理通常是确保一致性的最“昂贵”的方式。即使 php 有任何类型的 testdelete 可用,这也是正确的,因为您需要在第一次运行时 testdelete 所有内容,然后执行第二次循环,这会花费时间(并且您有可能在同时)。还有其他选择:

  1. 尝试隔离真正需要保存事务并处理数据库中的这些数据访问。例如。MySQL/InnoDB 支持事务处理的所有细节
  2. 定义并实施专用的“写/锁定所有权”。因此,您有带有子项目的文件夹 A 和 B,并且您的 php 被允许锁定 A 中的文件,而其他一些进程被允许锁定 B 中的文件。您的 php 和其他进程都被允许读取 A 和 B。这变得很棘手在文件上,因为文件读取也会导致锁定,文件越大,锁定的时间越长。因此,在文件的基础上,您可能需要通过文件大小限制、期限等来丰富它。
  3. 定义和实施专用访问时间框架。例如。所有文件都可以在一周内使用,但您在周日晚上有一个维护时间框架,它也可以运行删除,因此需要无锁环境。

对,假设我的推理不够可怕:) - 无论如何你都实现了事务保存文件删除 - 你的例程可以这样实现:

  1. 备份所有文件
  2. 如果备份失败,您可以尝试第二次、第三次、第四次(这是一个实施决定)
  3. 如果没有成功备份,则完全停止
  4. 运行您的删除过程,两个实现选项(以任何方式您需要记录您成功删除的文件):
    • 始终完全运行,并记录所有错误(这可以稍后作为家庭作业任务列表返回给用户,但可能会运行很长时间)
    • 运行并在第一个错误处停止
  5. 如果删除成功,则一切正常/句号;如果不继续回滚
  6. 仅从存档中复制以前成功删除的文件(只有他们!)
  7. 清除您的备份

那么这只是文件级别的事务保存。它不处理有人在第 5 步和第 6 步之间更改文件夹权限的情况。

于 2013-10-10T07:30:32.457 回答
0

或者您可以尝试将目录重命名/移动到 /tmp/ 之类的目录,它成功或不成功 - 但文件并没有消失。即使另一个进程有一个打开的句柄,移动也应该没问题。当 tmp 文件夹被清空时,这些文件将在一段时间后消失。

于 2013-12-10T11:26:27.813 回答