PHP在使用fclose关闭文件后无法删除文件。

11
在我的脚本完成后,我可以删除该文件,但在脚本运行时,即使使用fclose(),我也不能操作该文件。以下是我正在尝试使用的代码:

在我的脚本完成后,我可以删除该文件,但在脚本运行时,即使使用fclose(),我也不能操作该文件。

    $Files = glob("$_SERVER[DOCUMENT_ROOT]/files/*.csv");

    $File = fopen($Files[0], "r");        

    //while (($Data = fgetcsv($File)) !== false) {...

    $i = 0;
    while (is_resource($File)) {
        $i && sleep(1);
        echo "Closing handle.\n";
        fclose($File);
        if (++$i > 5)
            die("Could not close handle.");
    }

foreach ($Files as $File) {
    $i = 0;
    while (file_exists($File)) {
        $i && sleep(1);
        echo "Deleting file.\n";
        @unlink($File);
        echo 'www-data@debian:~$ ', $Command = "rm -f '$File' 2>&1", "\n", shell_exec($Command);
        if (++$i > 5)
            die("Could not delete the file.");
    }
}

正如你所看到的,我试图通过unlink()和使用shell命令来删除它,但两者都无法工作,都给了我这个错误:

rm:无法删除 'invincible-file.csv': 文本文件正忙

我也意识到脚本可能有点过度设计,但那纯粹是因为我无论如何都无法让它工作,而一些额外的代码只是用于输出目的,以尝试调试正在发生的事情。


4
$Files的内容是什么?此外,您使用“r”模式的fopen进行读取,并尝试稍后删除文件。您确定用户有权限删除吗?也许这是一个权限问题。尝试只执行unlink而不包含其他代码。 - Cave Johnson
2
移除 unlink 前面的 @,这样你就可以让 PHP 告诉你它为什么失败了。同时,检查 fclose 的返回值。 - chiliNUT
@bishop 的底层系统是NTFS,它运行在主机上(一个Debian虚拟机中,通过Virtual Box共享文件夹实现共享)。 - Brian Leishman
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Cave Johnson
@KodosJohnson 没有,我还没做到那一步,不过我尝试了你的答案,它解决了我的问题。 - Brian Leishman
显示剩余4条评论
1个回答

8

我之前遇到过这个问题,可以通过在关闭文件之后和删除文件之前强制进行垃圾回收来解决:

gc_collect_cycles();

这并不是最好的解决方案,但它确实解决了一个问题,即删除之前已经打开和关闭过的行的文件。


太棒了,其他地方我找不到在fclose()之后运行此函数的方法,但这个方法完美地解决了问题,非常感谢。 - Brian Leishman
你认为清除缓存(clearstatcache)是否可以帮助解决这种溢出问题? - Martin
@BrianLeishman 你能否在 fclose 前尝试使用 fflush,而不需要使用 gc_collect_cycles 的 hack? - bishop
1
这个问题也会出现在使用touch创建的文件中,同样的解决方案也适用于它。我曾经使用touch命令创建一个文件作为互斥锁,以防止同一脚本在同时运行时重叠。但是我无法在脚本结束时unlink该文件。 - Mohyaddin Alaoddin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接