2

我正在使用 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看到“互斥类”,但不确定它是否稳定并且有人尝试过。

4

4 回答 4

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!');
}
于 2013-05-12T14:29:14.293 回答
1

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

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

当然,如果您手动执行,实际上仍然可以同时启动两个 myprogram 实例,但 crond 只会创建一个。

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

于 2013-05-17T12:26:28.970 回答
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

于 2013-05-06T07:39:56.160 回答
0

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

于 2013-05-12T19:42:35.000 回答