0

次のコードを使用して、PHP でデータを作成して tar アーカイブに追加しています。問題は、phar が tar ファイルに対して排他ロックを使用しないことであり、同じファイルにアトミックな書き込みを行うと問題が発生します。

function phar_put_contents($fname, $archive, $data) { 
  $i=0;
  do { 
    $fp = @fopen($archive.'.lock', 'w');
    if(!$fp) { 
      usleep(25);
      continue;
    } 
    if(flock($fp, LOCK_EX)) { 
      try{
        $myPhar = new PharData($archive.'.tar',0);
        $myPhar[$fname] = $data;
        $myPhar->stopBuffering();
        flock($fp, LOCK_UN) && @fclose($fp);
        @unlink($archive.'.lock');
        return true;
      } catch (Exception $e) { 
        error_log($e->getMessage()." in ".$e->getFile().":".$e->getLine(),0);
        unset($e);
        @flock($fp, LOCK_UN) && @fclose($fp);
      } 
    } 
  } while ($i++<8);
  return false;
}

ルック ファイルを使用することは「良い」解決策のように思えますが、アーカイブが頻繁に破損するため、最適ではありません。

4

1 に答える 1

0

OK、PHP の Phar および PharData クラスはやや未完成のようです。外部ロックに対する私のアプローチは機能していlock()ません。close()

次のコードは、データを tar アーカイブに追加する機能を持たせるために使用したものです。

function phar_put_contents($fname, $archive, $data) { 
  $i=0;
  do { 
    $fp = @fopen($archive.'.lock', 'w');
    if(!$fp) { 
      usleep(25);
      continue;
    } 
    if(flock($fp, LOCK_EX)) { 
      try{
        file_put_contents('/tmp/'.$fname, $data);
        $tarCmd = "tar ". (file_exists($archive.".tar") ? "-rf ":"-cf ") .$archive.".tar  -C /tmp ".$fname;
        exec($tarCmd, $result, $status);
        if($status!=0)
          throw new Exception($tarCmd . implode($result, "\n"));
        @unlink('/tmp/'.$fname);
        flock($fp, LOCK_UN) && @fclose($fp);
        @unlink($archive.'.lock');
        return true;
      } catch (Exception $e) { 
        error_log($e->getMessage()." in ".$e->getFile().":".$e->getLine(),0);
        unset($e);
        @flock($fp, LOCK_UN) && @fclose($fp);
      } 
    } 
  } while ($i++<8);
  return false;
}

exec()の外部バージョンを使用して呼び出していることに注意してくださいtar。Phar は非常に信頼性の低いアーカイブへのフラッシュを行い、コードの 2 つのインスタンスが同時に同じファイルを変更できるため、tar ファイルが破損するため、これは必要でした。

于 2013-02-26T21:35:04.397 に答える