【问题标题】:How to run a php process as a singleton如何将 php 进程作为单例运行
【发布时间】:2012-05-28 11:43:32
【问题描述】:

我看到了一个 PHP 代码,它使用 shell 命令来确定这个进程现在是否正在运行,但是我把它弄丢了。你能告诉我怎么做吗?

我们的想法是创建一个 php 文件并使用 php -f 将此文件作为 cron 作业运行。脚本的执行时间可能是 10 秒,也可能是 10 分钟。我需要让这个 cron 每分钟运行一次,如果前一分钟的 cron 仍在运行 - 停止新的 cron 并让另一个完成。

我不太擅长 shell 编程,所以我需要一些帮助。

P.S 这个想法是创建一个守护进程,而不是在后台放置一个无休止的 PHP 进程。

【问题讨论】:

    标签: php shell


    【解决方案1】:

    您应该尝试在锁定文件上获取独占非阻塞锁定。如果你成功了,你的进程是唯一正在运行的实例,你应该保持锁定直到你终止。如果你没有成功获取锁,那么已经有另一个正在运行的实例,你应该终止。

    【讨论】:

      【解决方案2】:

      出于许多目的,以下代码是可以的(可能存在竞争条件,但对于一个微小的 cronjob,这可能非常罕见):

      if (file_exists($lockfilename)) {
         ... // lock is already taken
      } else {
         if ( !file_put_contents($lockfilename, $lockstring)) {
            error("unable to write $lockfilename");
         }
         $lock_taken = true;
         ... // do what you have to do
         if ( !unlink($lockfilename)) {
            warning("unable to unlink $lockfilename");
         }
         $lock_taken = false;
      }
      

      全局变量$lock_taken 可能有助于确保在暂停执行时删除锁定文件。 $lockstring 可以是日期或 Unix 时间戳,如果它明显太旧,这可能有助于解除锁定(但 filemtime() 可能就足够了)。

      如果你绝对不能冒竞争条件的风险,你必须做类似的事情

      if ( !($lockfile = fopen($lockfilename, "x"))) {
         ... // lock is already taken
      } else {
         $lock_taken = true;
         ... // write something to lockfile (optional)
         fclose($lockfile);
         ... // do what you have to do
         if ( !unlink($lockfilename)) {
            warning("unable to unlink $lockfilename");
         }
         $lock_taken = false;
      }
      

      不过,这只适用于本地锁文件。

      【讨论】:

        【解决方案3】:

        独占文件锁定方法比“检查文件是否存在”方法更好,因为如果脚本在您删除文件之前崩溃,那么锁定仍然存在。

        这是文件锁定的代码:

        //Allow only one instance
        $fileHandler = fopen('file_lock.lock', 'w');
        $hasLock = flock($fileHandler, LOCK_EX | LOCK_NB);
        if (!$hasLock)
            die("Another instance is already running");
        
        //do work
        
        //release lock
        flock($fileHandler, LOCK_UN);
        fclose($fileHandler);
        

        释放锁块是可选的,因为脚本执行后系统会自动释放锁。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-03-21
          • 1970-01-01
          • 2011-01-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-07-12
          相关资源
          最近更新 更多