【问题标题】:How can I ensure I have only one instance of a PHP script running via Apache?如何确保我只有一个通过 Apache 运行的 PHP 脚本实例?
【发布时间】:2018-01-11 17:16:44
【问题描述】:

我有一个 index.php 脚本,用作 Google 代码网站上的提交后 URL。此脚本克隆一个目录并构建一个可能需要一些工作的项目。我想避免让这个脚本并行运行不止一次。

如果另一个脚本已经在会话中,我可以使用一种机制来避免执行该脚本吗?

【问题讨论】:

    标签: php apache


    【解决方案1】:

    您可以使用flockLOCK_EX 来获得文件的排他锁。

    例如:

    <?php
    $fp = fopen('/tmp/php-commit.lock', 'r+');
    if (!flock($fp, LOCK_EX | LOCK_NB)) {
        exit;
    }
    
    // ... do stuff
    
    fclose($fp);
    ?>
    

    对于 5.3.2 之后的 PHP 版本,您需要使用手动释放锁 羊群($fp, LOCK_UN);

    【讨论】:

    • @LongEars 提到这段代码实际上在 Windows 上运行另一个实例,因为根据flock 上的 PHP 手册,LOCK_NB 在那里不起作用。它将在flock 上等待,直到之前的实例完成,然后运行整个代码。
    • 另外,为确保按预期工作,您可能需要将 fopen 模式更改为:$fp = fopen('/tmp/php-commit.lock', 'c'); 如果 commit.lock 文件不存在,使用 'r+' 会引发 PHP 错误。
    • 当 php 脚本崩溃时会发生什么,即抛出异常,而不执行 fclose ?然后可以启动另一个实例吗?
    • 对于 AMB,操作系统负责在 SCRIPT TERMINATION(而不是 fclose)上为您清理它。
    【解决方案2】:

    运行需要多长时间。

    可以使用内存缓存

    <?php
    $m = new Memcache(); // check the constructor call
    
    if( $m->get( 'job_running' ) ) exit;
    
    else $m->set( 'job_running', true );
    
    
    
    //index code here
    
    //at the end of the script
    
    $m->delete( 'job_running' );
    
    ?>
    

    如果任务失败,您需要从内存缓存中清除。 Flock 也是一个不错的选择……实际上可能更好。

    【讨论】:

    • 为了避免手动清除任务失败,您可以根据任务运行时间的某个顶部边界对集合使用时间限制。
    【解决方案3】:

    仅当您保存正在运行的脚本的状态并检查脚本何时启动时是否有其他脚本当前处于活动状态。

    例如,如果脚本正在运行,您可以执行以下操作来保存:

    $state = file_get_contents('state.txt');
    
    if (!$state) {
       file_put_contents('state.txt', 'RUNNING, started at '.time());
    
       // Do your stuff here...
    
       // When your stuff is finished, empty file
       file_put_contents('state.txt', '');
    }
    

    【讨论】:

      猜你喜欢
      • 2011-09-22
      • 1970-01-01
      • 1970-01-01
      • 2011-07-20
      • 2010-09-16
      • 2017-10-01
      • 1970-01-01
      • 2010-12-19
      相关资源
      最近更新 更多