1

複数のページへの複数の接続がある場合、ファイルの削除でエラーが発生します。エラー:Warning: unlink(folder/1.txt.txt) [function.unlink]: Permission denied in C:\htdocs\fopen.php on line 7

Note:すべてにアクセスするための 1 つの接続のみが正常に発生する場合 (エラーは発生しません)。

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

4

2 に答える 2

3

2 つのプロセスが同じファイルを同時にコピーおよび削除しようとしているため、問題が発生しています。これらは別個のプロセスであるため、処理の順序を簡単に制御することはできません。

fastWrite()同時に実行されている 2 つのプロセスを想像してください。

  • 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);
}
于 2012-11-10T17:06:46.500 に答える
1

問題は、 1.txt.txtに書き込み、削除するスクリプトが 2 つ以上あることです。これは競合状態と呼ばれます。Script1.phpには、 Script2.phpがファイルを使用しているかどうかを直接知る方法はありません。このメカニズムを自分で実装する必要があります。

簡単な解決策は、共有ファイルを使用する前にロック ファイルを作成し、使用が終了したらロック ファイルを削除することです。

2 つのスクリプトが同時にロック ファイルを作成しないようにするにはどうすればよいでしょうか。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: 私のシステムでは競合状態を再現できませんでした。

于 2012-11-10T17:37:18.673 に答える