【问题标题】:PHP: Safe way to remove a directory?PHP:删除目录的安全方法?
【发布时间】:2013-10-16 20:42:22
【问题描述】:

考虑这段代码:

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

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

【问题讨论】:

  • 您可以使用flock() 锁定文件,但除了实际删除之外,无法检查文件/目录是否可以删除。不过,您可以事先检查 chmod 权限,或者使用is_writable() 或类似的东西检查它是否可写。
  • 这也可以用fileperms() 完成...
  • 就算权限没问题,不知道文件在别的进程打开会不会被删除。
  • 复制它,删除它,如果删除则复制回来,否则抛出删除消息失败...
  • 使用这段代码 exec("rm -rf $yourdirpath");

标签: php unlink opendir rmdir


【解决方案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 步之间更改文件夹权限的情况。

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 如果文件夹中的任何文件具有打开的句柄,我认为该文件夹无法移动?
    猜你喜欢
    • 2023-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-25
    • 1970-01-01
    相关资源
    最近更新 更多