确保在后台运行一个php脚本副本

时间:2013-05-05 21:17:00

标签: php background cron mutex

我正在使用cronjob来运行将每1分钟执行一次的php脚本

我还需要确保只运行副本,所以如果这个php脚本在2分钟后仍在运行,那么cronjob不应该运行另一个版本。

目前我有2个选项,我希望看到您的反馈,如果您有更多选择

选项1:当php脚本启动时创建一个tmp文件,当php脚本完成时删除它(并检查文件是否存在)--->我有这个选项的问题是,如果我的PHP脚本因任何原因崩溃,它将不会再次运行(tmp文件不会被删除)

选项2:运行类似下面的bash脚本来控制php脚本执行--->好,但寻找可以在PHP内完成的事情

#!/bin/bash
function rerun {
        BASEDIR=$(dirname $0)
        echo $BASEDIR/$1
        if ps -ef | grep -v grep | grep $1; then
            echo "Running"
            exit 0
    else
            echo "NOT running";
            /usr/local/bin/php $BASEDIR/$1 &
            exit $?
    fi

}  
rerun myphpscript.php
PS:我刚刚在http://www.php.net/manual/en/class.mutex.php看到了“Mutex课程”,但不确定它是否稳定且有人试过。

4 个答案:

答案 0 :(得分:1)

您可能希望使用我的库ninja-mutex,它提供了处理互斥锁的简单界面。目前它可以使用flock,memcache,redis或mysql来处理锁定。

下面是一个使用memcache的例子:

<?php
require 'vendor/autoload.php';

use NinjaMutex\Lock\MemcacheLock;
use NinjaMutex\Mutex;

$memcache = new Memcache();
$memcache->connect('127.0.0.1', 11211);
$lock = new MemcacheLock($memcache);
$mutex = new Mutex('very-critical-stuff', $lock);
if ($mutex->acquireLock(1000)) {
    // Do some very critical stuff

    // and release lock after you finish
    $mutex->releaseLock();
} else {
    throw new Exception('Unable to gain lock!');
}

答案 1 :(得分:1)

我经常在我的crontabs中直接使用许多Linux发行版附带的程序flock,如:

* * * * * flock -n /var/run/mylock.LCK /usr/local/bin/myprogram

原因是如果你手动执行它仍然可以实际启动两个myprogram实例,但是crond只能创建一个。

Flock是一个小型的编译二进制文件,与最终的大量php代码相比,它的启动速度非常快。如果您有许多更长时间运行的执行,这尤其是一个好处,实际上并不是很清楚。

答案 2 :(得分:0)

如果您没有使用NFS挂载,可以使用flock()(http://php.net/manual/en/function.flock.php):

$fh = fopen('guestbook.txt','a')         or die($php_errormsg);
$tries = 3;
while ($tries > 0) {
    $locked = flock($fh,LOCK_EX | LOCK_NB);
    if (! $locked) {
        sleep(5);
        $tries--;
    } else {
        // don't go through the loop again 
        $tries = 0;
    }
}
if ($locked) {
    fwrite($fh,$_REQUEST['guestbook_entry']) or die($php_errormsg);
    fflush($fh)                              or die($php_errormsg);
    flock($fh,LOCK_UN)                       or die($php_errormsg);
    fclose($fh)                              or die($php_errormsg);
} else {
    print "Can't get lock.";
}  

来自:http://docstore.mik.ua/orelly/webprog/pcook/ch18_25.htm

答案 3 :(得分:0)

我发现最适合我的解决方案是为脚本创建一个单独的数据库用户,并将该用户的concurent连接限制为1。