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

好的,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 对存档进行非常不可靠的刷新,导致 tar 文件损坏,因为代码的两个实例可以同时修改同一个文件。

于 2013-02-26T21:35:04.397 回答