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



我使用cronjob运行php脚本,每1分钟执行一次

我还需要确保只有一个副本正在运行,所以如果这个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,但不确定它是否稳定,有人尝试过。

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

下面是一个使用memcache的例子:
<?php
require 'vendor/autoload.php';
use NinjaMutexLockMemcacheLock;
use NinjaMutexMutex;
$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!');
}

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

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

当然,如果你手工操作的话,仍然有可能同时启动myprogram的两个实例,但是crond只会创建一个。

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

如果没有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

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

最新更新