PHP:删除目录的安全方法


PHP: Safe way to remove a directory?

请考虑以下代码:

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);
    }
}

这将删除目录。但是,如果取消链接失败或 opendir 在任何子目录上失败,则该目录将留下一些内容。

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

我一般我会确认评论:

"复制它,删除

它,如果删除,则复制回来,否则抛出删除消息失败......" – 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 之间更改文件夹权限的情况。

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