PHP错误删除文件

时间:2012-11-10 16:55:41

标签: php file-permissions permission-denied unlink

如果多个页面有多个连接,则删除文件时出错。 错误:Warning: unlink(folder/1.txt.txt) [function.unlink]: Permission denied in C:\htdocs\fopen.php on line 7

Note:如果只有一个连接可以访问所有内容(通常不会发生错误)。

PHP代码fopen.php

<?php
function fastWrite($a){
    echo 'Coping file: "',$a,'" to "',$a,'.txt"<br>';
    copy($a,$a.'.txt');

    echo 'Delete file: "',$a,'.txt"<br>';
    unlink($a.'.txt');
}

for($i=0;$i<10;$i++){
    fastWrite('folder/1.txt');
    echo '<hr>';
}
?>

html / javascript代码(模拟多个连接):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
<title>my test</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script type="text/javascript">
function myTest(z){
    $.ajax("fopen.php?time="+(new Date().getTime()),{"success":function(data){
        $("<div></div>").addClass("sty").html(data).appendTo("body");
    },"error":function(a,b,c){
        $("<div></div>").addClass("sty").html([a,b,c]).appendTo("body");
    }});
}
</script>
<style>
.sty{
border:1px #000 solid;
overflow:auto;
margin:5px 0 0 5px;
}
</style>
</head>
<body>
<p><a href="teste.html">New test</a></p>
<script type="text/javascript">
var dd = "";
for(var i=0;i<10;i++){
    dd += "myTest(\"#a"+(i+1)+"\");\n";
}
eval(dd);
</script>
</body>
</html>

我做错了什么?

感谢。


解决方案: clearstatcache

2 个答案:

答案 0 :(得分:3)

您遇到问题,因为有两个进程正在尝试同时复制和删除同一个文件。因为它们是独立的过程,所以你无法轻易控制它们的工作顺序。

想象一下两个进程,同时运行fastWrite()

  • t1将'a'复制到'a.txt'
  • t2将'a'复制到'a.txt'
  • t2删除'a.txt'
  • t1尝试删除'a.txt',但由于它不存在而失败

这被称为“竞争条件”。

如果您不介意unlink调用有时会失败,您可以使用命令前面的'@'符号忽略错误:

@unlink("$a.txt");

我很确定将用户生成的数据一次又一次地保存到同一个文件中并不是您的最终目标。你在追求更大的东西时显然遇到了这个问题。也许你应该开始一个更关注那个问题的新问题。

如果您只需要在连接期间使用临时文件,请不要始终将文件命名为相同。相反,你可以:

function doStuffToFile($fname) {
    $tempName = $fname . "." . getmypid() . "." . rand();
    copy($fname, $tempName);
    // do stuff to your temporary file
    unlink($tempName);
}

答案 1 :(得分:1)

问题是您有两个或更多脚本可以写入并删除 1.txt.txt 。这被称为竞争条件。 Script1.php 无法直接了解 Script2.php 是否正在使用文件,您需要自己实现此机制。

一个简单的解决方案是在使用共享文件之前创建一个锁文件,并在完成后删除锁文件。

然后出现了一个新问题:如何确保两个脚本不会立即创建锁定文件? Script1.php 可能会发现锁定文件不存在但在实际创建文件之前,处理器切换到 Script2.php ,它也会发现缺少锁定文件。那么呢?

PHP提供了一个有用的flock函数。我不知道血淋淋的细节,但我相信它至少应该在某些平台上解决你的问题。

<?php
function fastWrite($a)
{
    # //// LOCK \\\\
    $fp = fopen("fastwrite.lock", "w");
    if (flock($fp, LOCK_EX) === false) { # PHP will stop at this line until the lock is acquired
        die("flock failed");
    }
    # \\\\ LOCK ////

    echo 'Coping file: "', $a, '" to "', $a, '.txt"<br>';
    copy($a, $a . '.txt');

    echo 'Delete file: "', $a, '.txt"<br>';
    unlink($a . '.txt');

    # //// UNLOCK \\\\
    if (flock($fp, LOCK_UN) === false) {
        die("flock failed");
    }
    fclose($fp);
    # \\\\ UNLOCK ////

}
for ($i = 0; $i < 10; $i++) {
    fastWrite('1.txt');
    echo '<hr>';
}

PS:我无法在我的系统上重现竞争条件。