PHP:删除目录的安全方法?

时间:2013-10-09 13:03:58

标签: php unlink opendir rmdir

考虑以下代码:

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在任何子目录上失败,那么该目录将留下一些内容。

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

2 个答案:

答案 0 :(得分:1)

我一般我会确认评论:

“复制它,删除它,如果删除则复制,否则丢弃删除消息失败......” - We0

但是让我们考虑一些方面:

尝试实现事务保存文件删除表示您希望在同一组文件上允许竞争文件锁定。事务处理通常是确保一致性的最“昂贵”方式。即使php有任何类型的testdelete可用也是如此,因为你需要在第一次运行时测试删除所有内容,然后再进行第二次循环,这会花费时间(并且你有危险在你的文件系统中发生了一些变化)与此同时)。还有其他选择:

  1. 尝试隔离真正需要事务保存的内容并处理数据库中的数据访问。例如。 MySQL / InnoDB支持事务处理的所有细节
  2. 定义并实施专用的“写入/锁定所有权”。所以你有文件夹A和B的子项,你的php可以锁定A中的文件,其他一些进程可以锁定B中的文件。你的php和其他进程都允许读取A和B.这很棘手在文件上,因为文件读取会导致锁定,文件越大,持续时间越长。因此,在文件基础上,您可能需要使用文件大小限制,容器期等来丰富它。
  3. 定义并实施专用访问时间范围。例如。所有文件都可以在一周内使用,但是你在星期天晚上有一个维护时间框架,它也可以运行删除,因此需要无锁环境。
  4. 是的,让我说我的理由不够可怕:) - 并且你实现了一个事务保存文件删除 - 你的例程可以这样实现:

    1. 备份所有文件
    2. 如果备份失败,您可以尝试第二次,第三次,第四次(这是一项实施决定)
    3. 如果没有成功备份,则完全停止
    4. 运行您的删除过程,两个实现选项(以任何方式您需要记录您成功删除的文件):
      • 始终完全运行,并记录所有错误(这可以在以后作为家庭作业任务列表返回给用户,但可能会长时间运行)
      • 贯穿并停在第一个错误
    5. 如果删除成功,则全部/完全停止;如果不继续回滚
    6. 仅从存档中复制以前成功删除的文件(仅限他们!)
    7. 擦除备份
    8. 这只是文件级别的事务保存。它不处理某人在步骤5和6之间更改文件夹权限的情况。

答案 1 :(得分:0)

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