【问题标题】:How to lock file in PHP?如何在 PHP 中锁定文件?
【发布时间】:2011-02-05 13:04:48
【问题描述】:

我正在尝试创建一个 PHP 文件,如果它已经在运行,它将不会运行。这是我正在使用的代码:

<?php

class Test {
    private $tmpfile;

    public function action_run() {
        $this->die_if_running();
        $this->run();
    }

    private function die_if_running() {
        $this->tmpfile = @fopen('.refresher2.pid', "w");

        $locked = @flock($this->tmpfile, LOCK_EX|LOCK_NB);
        if (! $locked) {
            @fclose($this->tmpfile);
            die("Running 2");
        }
    }

    private function run() {
        echo "NOT RUNNNING";
        sleep(100);
    }
}

$test = new Test();
$test->action_run();

问题是,当我从控制台运行它时,它运行良好。但是当我尝试从浏览器运行它时,许多实例可以同时运行。这是在 Windows 7、XAMPP、PHP 5.3.2 上。我猜操作系统认为这是相同的过程,因此功能下降。有没有跨平台的方式来创建这种类型的 PHP 脚本?

【问题讨论】:

  • flock 文档说 LOCK_NB 在 Windows 上不受支持。使用静默运算符 (@) 是一个非常糟糕的主意,您实际上可能会抑制您遇到的错误。
  • @Evert,感谢您的建议,我复制了锁定代码,但没有删除@,但它没有显示任何错误

标签: php apache locking


【解决方案1】:

没有什么可承诺的。你不能像这样使用flock。

您可以使用 system() 来启动另一个 (php) 进程来为您进行锁定。但缺点:

  • 您需要进行进程间通信。考虑一种方法如何告诉其他程序何时释放锁等。您可以使用标准输入进行消息传递和使用 3 个常量或其他东西。这种情况下还是比较简单的
  • 这对性能不利,因为您不断创建昂贵的流程。

另一种方法是启动另一个一直运行的程序。您使用某种 IPC 方式连接到它(可能只使用 tcp 通道,因为它是跨平台的)并允许该程序管理文件访问。该程序也可以是一个无限循环中的 php 脚本,但用 Java 或其他支持多线程的语言编写它可能会更简单。

另一种方法是利用现有资源。为锁创建一个虚拟数据库表,为文件创建一个条目,然后执行 table-row-locking。

另一种方法是不使用文件,而是使用数据库。

【讨论】:

  • @Downvoter:这有什么问题?如果你投反对票,你至少应该评论为什么!
【解决方案2】:

不久前我遇到了类似的问题。 我需要有一个计数器,返回的数字是唯一的。 我使用了一个锁定文件,只有当这个实例能够创建锁定文件时,它才允许读取当前编号的文件。

也许您可以允许脚本运行,而不是计数。 诀窍是让尝试几次(比如 5 次),中间稍作等待/睡眠。

function GetNextNumber()
{
  $lockFile = "lockFile.txt";
  $lfh = @fopen($lockFile, "x");
  if (!$lfh)
  {
    $lockOkay = false;
    $count = 0;
    $countMax = 5;

    // Try ones every second in 5 seconds
    while (!$lockOkay & $count < $countMax) 
    {
      $lfh = @fopen($lockFile, "x");
      if ($lfh)
      {
        $lockOkay = true;
      }
      else
      {
        $count++;
        sleep(1);
      }
    }
  }

  if ($lfh)
  {
    $fh = fopen($myFile, 'r+') or die("Too many users. ");
    flock($fh, LOCK_EX);
    $O_nextNumber = fread($fh, 15);
    $O_nextNumber = $O_nextNumber + 1;
    rewind($fh);
    fwrite($fh, $O_knr);
    flock($fh, LOCK_UN);  
    fclose($fh);

    unlink($lockFile); // Sletter lockfilen
  }

  return $O_nextNumber;
}

【讨论】:

    猜你喜欢
    • 2011-08-24
    • 2011-07-23
    • 2015-04-14
    • 2018-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-26
    • 1970-01-01
    相关资源
    最近更新 更多