2011-07-21 29 views
0

当用户上传文件锁文件,而不使用羊群

exec('nohup php /main/apache2/work/upload/run.php &'); 

我使用nohup因为它需要在后端被执行(用户可以上传多个文件)。

在我的原始设计run.php每次执行时都会使用scandir扫描目录。使用flock获取文件上的独占锁LOCK_EX,并使用LOCK_NB跳过该文件,如果它有锁并转到下一个文件。如果文件有锁//Do logic。问题是服务器缺少fcntl()库,并且由于flock使用该库来执行锁定机制,因此flock目前不起作用。这将需要一个月或两个月才能完成(我无法控制)。

因此,我的工作是有一个临时文件lock.txt作为锁。如果文件名存在于lock.txt中,则跳过该文件并转到下一个文件。

$dir = "/main/apache2/work/upload/files/"; 
$files = scandir($dir); 
$fileName = "lock.txt"; 

for($i=0; $i<count($files); $i++) 
{ 
    if(substr(strrchr($files[$i],'.csv'),-4) == '.csv') 
    {   
     if($file_handle = fopen("$fileName", "rb")) 
     { 
      while(!feof($file_handle)) 
      { 
       $line = fgets($file_handle); 
       $line = rtrim($line); 
       if($line == "") 
       { 
        break; 
       } 
       else 
       { 
        if($files[$i] == $line) 
        { 
         echo "Reading from lock: ".$line."</br>"; 
         $i++; //Go to next file 
        } 
       } 

      } 
      fclose($file_handle); 
     } 

     if($i >= count($files)) 
     { 
      die("$i End of file"); 
     } 

     if($file_handle = fopen("$fileName", "a+")) 
     { 
      if(is_writable($fileName)) 
      {    
       $write = fputs($file_handle, "$files[$i]"."\n"); 
       //Do logic 

       //Delete the file name - Stuck here 

       fclose($file_handle); 
      } 

     } 

    } 
    else 
    { 
     //Do nothing 
    } 
} 

如何从lock.txt删除文件名?

更重要的是,有没有更好的方法来锁定一个文件在php中,而不使用flock

+1

您的运行backlground过程的方法存在缺陷 - 请参阅http://symcbean.blogspot.com/2010/02/php-and-long-running-processes.html – symcbean

+0

谢谢:) – theking963

回答

1

拥有共享锁数据库只是将锁定问题移动到该文件;它并没有解决它。

更好的解决方案是每个真实文件使用一个锁文件。如果要锁定对myFile.csv的访问权限,请检查file_exists('myFile.csv.lock')touch('myFile.csv.lock')(如果不存在)。完成后,请拨打unlink('myFile.csv.lock')

现在,file_exists()和touch()之间可能存在竞争条件,可以通过将PID存储在文件中并检查getmypid()是否确实是持有锁的进程来缓解这种情况。